ffmpegxugglexuggler

Transcoding audio using xuggler


I am trying to convert an audio file with the header

Opening audio decoder: [pcm] Uncompressed PCM audio decoder
AUDIO: 44100 Hz, 2 ch, s16le, 1411.2 kbit/100.00% (ratio: 176400->176400)
Selected audio codec: [pcm] afm: pcm (Uncompressed PCM)

I want to transcode this file to mp3 format. I have following code snippet but its not working well. I have written it using XUGGLER code snippet for transcoding audio and video.

Audio decoder is

    audioDecoder = IStreamCoder.make(IStreamCoder.Direction.DECODING, ICodec.findDecodingCodec(ICodec.ID.CODEC_ID_PCM_S16LE));
    audioDecoder.setSampleRate(44100);
    audioDecoder.setBitRate(176400);
    audioDecoder.setChannels(2);
    audioDecoder.setTimeBase(IRational.make(1,1000));
    if (audioDecoder.open(IMetaData.make(), IMetaData.make()) < 0)
        return false;
    return true; 

Audio encoder is

    outContainer = IContainer.make();
    outContainerFormat = IContainerFormat.make();
    outContainerFormat.setOutputFormat("mp3", urlOut, null);
    int retVal = outContainer.open(urlOut, IContainer.Type.WRITE, outContainerFormat);
    if (retVal < 0) {
        System.out.println("Could not open output container");
        return false;
    }
    outAudioCoder = IStreamCoder.make(IStreamCoder.Direction.ENCODING, ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_MP3));
    outAudioStream = outContainer.addNewStream(outAudioCoder);
    outAudioCoder.setSampleRate(new Integer(44100));
    outAudioCoder.setChannels(2);
    retVal = outAudioCoder.open(IMetaData.make(), IMetaData.make());
    if (retVal < 0) {
        System.out.println("Could not open audio coder");
        return false;
    }
    retVal = outContainer.writeHeader();
    if (retVal < 0) {
        System.out.println("Could not write output FLV header: ");
        return false;
    }
    return true;

And here is encode method where i send packets of 32 byte to transcode

public void encode(byte[] audioFrame){
    //duration of 1 video frame
    long lastVideoPts = 0;

    IPacket packet_out = IPacket.make();
    int lastPos = 0;
    int lastPos_out = 0;

    IAudioSamples audioSamples = IAudioSamples.make(48000, audioDecoder.getChannels());
    IAudioSamples audioSamples_resampled = IAudioSamples.make(48000, audioDecoder.getChannels());

    //we always have 32 bytes/sample
    int pos = 0;
    int audioFrameLength = audioFrame.length;
    int audioFrameCnt = 1;
    iBuffer = IBuffer.make(null, audioFrame, 0, audioFrameLength);
    IPacket packet = IPacket.make(iBuffer);
    //packet.setKeyPacket(true);
    packet.setTimeBase(IRational.make(1,1000));
    packet.setDuration(20);
    packet.setDts(audioFrameCnt*20);
    packet.setPts(audioFrameCnt*20);
    packet.setStreamIndex(1);
    packet.setPosition(lastPos);
    lastPos+=audioFrameLength;
    int pksz = packet.getSize();
    packet.setComplete(true, pksz);
    /*
    * A packet can actually contain multiple samples
    */
    int offset = 0;
    int retVal;
    while(offset < packet.getSize())
    {
        int bytesDecoded = audioDecoder.decodeAudio(audioSamples, packet, offset);
        if (bytesDecoded < 0)
            throw new RuntimeException("got error decoding audio ");
        offset += bytesDecoded;
        if (audioSamples.isComplete())
        {
            int samplesConsumed = 0;
            while (samplesConsumed < audioSamples.getNumSamples()) {
                retVal = outAudioCoder.encodeAudio(packet_out, audioSamples, samplesConsumed);
                if (retVal <= 0)
                    throw new RuntimeException("Could not encode audio");
                samplesConsumed += retVal;
                if (packet_out.isComplete()) {
                    packet_out.setPosition(lastPos_out);
                    packet_out.setStreamIndex(1);
                    lastPos_out+=packet_out.getSize();
                    retVal = outContainer.writePacket(packet_out);
                    if(retVal < 0){
                        throw new RuntimeException("Could not write data packet");
                    }
                }
            }
        }

    }

}

I get an output file but it doesnt get played. I have very little experience of audio encoding and sampling. Thanks in advance.


Solution

  • Finally I am able to live transcode a pcm stream to mp3 stream.

    There were couple of issues in the code :

    NOTE : this is a pretty old code

     byte[] data = new byte[418];
    
    public void encode(byte[] audioFrame) {
        IPacket packet_out = IPacket.make();
        int lastPos_out = 0;
    
    
        IAudioSamples audioSamples = IAudioSamples.make(11025, audioDecoder.getChannels());
        //IAudioSamples audioSamples_resampled = IAudioSamples.make(48000, audioDecoder.getChannels());
    
        //we always have 32 bytes/sample
        int pos = 0;
        int audioFrameLength = audioFrame.length;
        int audioFrameCnt = 1;
        iBuffer = IBuffer.make(null, audioFrame, 0, audioFrameLength);
        IPacket packet = IPacket.make(iBuffer);
        //packet.setKeyPacket(true);
        packet.setTimeBase(IRational.make(1, 1000));
        packet.setStreamIndex(0);
        int pksz = packet.getSize();
        packet.setComplete(true, pksz);
       /*
        * A packet can actually contain multiple samples
        */
        int offset = 0;
        int retVal;
        while (offset < packet.getSize()) {
            int bytesDecoded = audioDecoder.decodeAudio(audioSamples, packet, offset);
            if (bytesDecoded < 0)
                throw new RuntimeException("got error decoding audio ");
            offset += bytesDecoded;
            if (audioSamples.isComplete()) {
                /*audioResampler.resample(audioSamples_resampled, audioSamples, audioSamples.getNumSamples());
                audioSamples_resampled.setPts(Global.NO_PTS);*/
                int samplesConsumed = 0;
                while (samplesConsumed < audioSamples.getNumSamples()) {
                    retVal = outAudioCoder.encodeAudio(packet_out, audioSamples, samplesConsumed);
                    if (retVal <= 0)
                        throw new RuntimeException("Could not encode audio");
                    samplesConsumed += retVal;
                    if (packet_out.isComplete()) {
                        packet_out.setPosition(lastPos_out);
                        packet_out.setStreamIndex(0);
                        lastPos_out += packet_out.getSize();
                        System.out.println("size" + packet_out.getSize());
                        packet_out.getByteBuffer().get(data,0,packet_out.getSize());
                        try {
                            fo.write(data);
                        } catch (IOException e) {
                            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                        }
                        packet_out.reset();
                        //retVal = outContainer.writePacket(packet_out);
                        if (retVal < 0) {
                            throw new RuntimeException("Could not write data packet");
                        }
                    }
                }
            }
        }
    }