#include "Modules/SimpleModule.hpp"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
class MpegDecodeModule : public SimpleModule {
public:
MpegDecodeModule() : videoCodecContext( 0 )
{
currentFrame = 0;
}
void init()
{
av_register_all();
if ( avcodec_open( videoCodecContext = avcodec_alloc_context(), &mpeg1video_decoder ) < 0 ) {
printf("error opening context\n");
videoCodecContext = 0;
}
}
void process( const Frame &frame )
{
AVPacket *pkt = ((FFMpegStreamPacket*)frame.data())->packet;
if ( !videoCodecContext ) {
printf("can't process video data without a context\n");
return;
}
if ( !currentFrame )
currentFrame = getAvailableFrame();
YUVFrame *yuvFrame = (YUVFrame *)currentFrame->data();
AVFrame *picture = yuvFrame->pic;
assert( videoCodecContext->pix_fmt == PIX_FMT_YUV420P );
//printf("processing video data (%i x %i)\n", videoCodecContext->width, videoCodecContext->height);
AVPacket *mpeg = pkt;
unsigned char *ptr = (unsigned char*)mpeg->data;
int count = 0, ret = 0, gotPicture = 0;
// videoCodecContext->hurry_up = 2;
int len = mpeg->size;
// for ( ; len && ret >= 0; len -= ret, ptr += ret )
ret = avcodec_decode_video( videoCodecContext, picture, &gotPicture, ptr, len );
frame.deref();
if ( gotPicture ) {
yuvFrame->width = videoCodecContext->width;
yuvFrame->height = videoCodecContext->height;
yuvFrame->fmt = videoCodecContext->pix_fmt;
SimpleModule::process( *currentFrame );
currentFrame = 0;
}
}
Frame* createNewFrame()
{
YUVFrame *yuvFrame = new YUVFrame;
yuvFrame->pic = avcodec_alloc_frame();
return new Frame( "FRAME_ID_YUV_VIDEO_FRAME", yuvFrame );
}
void reuseFrame( Frame *frame )
{
YUVFrame *yuvFrame = (YUVFrame *)frame->data();
av_free( yuvFrame->pic );
yuvFrame->pic = avcodec_alloc_frame();
}
const char *name() { return "Mpeg1 Video Decoder"; }
Format inputFormat() { return "FRAME_ID_MPEG1_VIDEO_PACKET"; }
Format outputFormat() { return "FRAME_ID_YUV_VIDEO_FRAME"; }
bool isBlocking() { return true; }
private:
Frame *currentFrame;
AVCodecContext *videoCodecContext;
};