/* * myLib - https://github.com/taktod/myLib * Copyright (c) 2014 ttProject. All rights reserved. * * Licensed under GNU AFFERO GENERAL PUBLIC LICENSE Version 3. */ package com.ttProject.humble.test; import java.nio.ByteBuffer; import io.humble.ferry.Buffer; import io.humble.video.AudioFormat.Type; import io.humble.video.Codec; import io.humble.video.AudioChannel.Layout; import io.humble.video.Codec.ID; import io.humble.video.Decoder; import io.humble.video.Encoder; import io.humble.video.MediaAudio; import io.humble.video.MediaAudioResampler; import io.humble.video.MediaPacket; //import io.humble.video.MediaPictureResampler; import io.humble.video.MediaPicture; import io.humble.video.MediaPictureResampler; import org.apache.log4j.Logger; import com.ttProject.container.IContainer; import com.ttProject.container.flv.FlvTagReader; import com.ttProject.container.flv.type.AudioTag; import com.ttProject.container.flv.type.VideoTag; import com.ttProject.frame.IAudioFrame; import com.ttProject.frame.IVideoFrame; import com.ttProject.humble.frameutil.Packetizer; import com.ttProject.nio.channels.FileReadChannel; import com.ttProject.nio.channels.IReadChannel; import com.ttProject.util.HexUtil; /** * flv convert test. * @author taktod */ public class FlvTest { /** logger */ private Logger logger = Logger.getLogger(FlvTest.class); private Packetizer packetizer = null; // audio private Decoder audioDecoder = null; private MediaAudioResampler audioResampler = null; private Encoder audioEncoder = null; // video private Decoder videoDecoder = null; private MediaPictureResampler videoResampler = null; private Encoder videoEncoder = null; /** * test * @throws Exception */ // @Test public void test() throws Exception { packetizer = new Packetizer(); IReadChannel source = FileReadChannel.openFileReadChannel( "http://49.212.39.17/mario.flv" ); // S_16 -> S_16P is not work... why? audioEncoder = Encoder.make(Codec.findEncodingCodec(ID.CODEC_ID_MP3)); audioEncoder.setSampleRate(44100); audioEncoder.setChannels(2); audioEncoder.setChannelLayout(Layout.CH_LAYOUT_STEREO); Type findFormat = null; for(Type format : audioEncoder.getCodec().getSupportedAudioFormats()) { if(findFormat == null) { findFormat = format; } if(format == Type.SAMPLE_FMT_FLT) { findFormat = format; break; } } if(findFormat == null) { throw new Exception("supported audioformat is unknown."); } audioEncoder.setSampleFormat(findFormat); audioEncoder.open(null, null); FlvTagReader reader = new FlvTagReader(); IContainer container = null; while((container = reader.read(source)) != null) { if(container instanceof AudioTag) { AudioTag aTag = (AudioTag)container; if(aTag.getFrame() != null) { // decodeAudio(aTag.getFrame()); } } else if(container instanceof VideoTag) { VideoTag vTag = (VideoTag)container; if(vTag.getFrame() != null) { decodeVideo(vTag.getFrame()); } } } } /** * decode video * @param frame */ private void decodeVideo(IVideoFrame frame) throws Exception { logger.info("decode video"); videoDecoder = packetizer.getDecoder(frame, videoDecoder); MediaPacket packet = packetizer.getPacket(frame, null); int offset = 0; while(offset < packet.getSize()) { logger.info(frame.getWidth()); logger.info(frame.getHeight()); MediaPicture picture = MediaPicture.make(frame.getWidth(), frame.getHeight(), io.humble.video.PixelFormat.Type.PIX_FMT_YUV420P); logger.info("here?"); int bytesDecoded = videoDecoder.decodeVideo(picture, packet, offset); if(bytesDecoded < 0) { throw new Exception("failed to decode data."); } offset += bytesDecoded; if(picture.isComplete()) { logger.info("decode OK:" + picture); } } } /** * decode audio * @param frame */ private void decodeAudio(IAudioFrame frame) throws Exception { logger.info("decode audio"); audioDecoder = packetizer.getDecoder(frame, audioDecoder); MediaPacket packet = packetizer.getPacket(frame, null); int offset = 0; while(offset < packet.getSize()) { MediaAudio samples = MediaAudio.make(frame.getSampleNum(), frame.getSampleRate(), frame.getChannel(), audioDecoder.getChannelLayout(), audioDecoder.getSampleFormat()); int bytesDecoded = audioDecoder.decodeAudio(samples, packet, offset); if(bytesDecoded < 0) { throw new Exception("failed to decode data."); } offset += bytesDecoded; if(samples.isComplete()) { MediaAudio sampled = getResampled(samples); logger.info("encode now."); encodeSound(sampled); } } logger.info("end"); } /** * audio resample. * @param samples * @return * @throws Exception */ private MediaAudio getResampled(MediaAudio samples) throws Exception { if(samples.getSampleRate() != audioEncoder.getSampleRate() || samples.getFormat() != audioEncoder.getSampleFormat() || samples.getChannels() != audioEncoder.getChannels() || samples.getChannelLayout() != audioEncoder.getChannelLayout()) { if(audioResampler == null || (samples.getSampleRate() != audioResampler.getInputSampleRate() || samples.getFormat() != audioResampler.getInputFormat() || samples.getChannels() != audioResampler.getInputChannels() || samples.getChannelLayout() != audioResampler.getInputLayout())) { audioResampler = MediaAudioResampler.make( audioEncoder.getChannelLayout(), audioEncoder.getSampleRate(), audioEncoder.getSampleFormat(), samples.getChannelLayout(), samples.getSampleRate(), samples.getFormat()); logger.info("need to resample, make resampler."); logger.info(audioResampler.getInputLayout()); logger.info(audioResampler.getInputFormat()); logger.info(audioResampler.getInputSampleRate()); logger.info(audioResampler.getInputChannels()); logger.info(audioResampler.getOutputLayout()); logger.info(audioResampler.getOutputFormat()); logger.info(audioResampler.getOutputSampleRate()); logger.info(audioResampler.getOutputChannels()); audioResampler.open(); } MediaAudio spl = MediaAudio.make(1024, audioEncoder.getSampleRate(), audioEncoder.getChannels(), audioEncoder.getChannelLayout(), audioEncoder.getSampleFormat()); int retval = audioResampler.resample(spl, samples); if(retval <= 0) { throw new Exception("failed to resample audio."); } spl.setTimeStamp(samples.getTimeStamp()); spl.setTimeBase(samples.getTimeBase()); return spl; } else { // no need for resample. return samples; } } /** * try encode. * @param samples * @throws Exception */ private void encodeSound(MediaAudio samples) throws Exception { // logger.info(samples.getNumSamples()); // while(sampleConsumed < samples.getNumSamples()) { while(true) { MediaPacket output = MediaPacket.make(); audioEncoder.encodeAudio(output, samples); logger.info(output); if(output.isComplete()) { Buffer buf = output.getData(); ByteBuffer buffer = buf.getByteBuffer(0, buf.getBufferSize()); logger.info(HexUtil.toHex(buffer, true)); } else { break; } // logger.info(samples.getNumSamples()); // break; } } }