
class MP3DecodeModule : public SimpleModule {
public:
    MP3DecodeModule() : audioCodecContext( 0 )
    {
    }
    
    void init()
    {
        av_register_all();
        
        if ( avcodec_open( audioCodecContext = avcodec_alloc_context(), &mp3_decoder ) < 0 ) {
            printf("error opening context\n");
            audioCodecContext = 0;
        }
    }
    
    void process( const Frame &frame ) 
    {
        AVPacket *pkt = ((FFMpegStreamPacket*)frame.data())->packet;

        Frame *f = getAvailableFrame();
        PCMData *pcm = (PCMData *)f->data();
        int count = 0, ret = 0, bytesRead;
        AVPacket *mp3 = pkt;
	unsigned char *ptr = (unsigned char*)mp3->data;
        for ( int len = mp3->size; len && ret >= 0; len -= ret, ptr += ret ) {
            ret = avcodec_decode_audio(audioCodecContext, (short*)(pcm->data + count), &bytesRead, ptr, len);
            if ( bytesRead > 0 )
                count += bytesRead;
	}
        frame.deref();

        pcm->size = count;
        SimpleModule::process( *f );
    }
    
    Frame* createNewFrame()
    {
        return new Frame( "FRAME_ID_PCM_AUDIO_DATA", new PCMData );
    }
    
    const char *name() { return "MP3 Decoder"; }
    Format inputFormat() { return "FRAME_ID_MPEG_AUDIO_PACKET"; }
    Format outputFormat() { return "FRAME_ID_PCM_AUDIO_DATA"; }
    bool isBlocking() { return true; }

private:
    AVCodecContext *audioCodecContext;
};

