class MpegEncodeModule : public SimpleModule {
public:
MpegEncodeModule() : videoCodecContext( 0 )
{
}
void init()
{
printf("S %i\n", __LINE__);
av_register_all();
videoCodecContext = avcodec_alloc_context();
AVCodec *codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
assert( codec );
/*
if ( avcodec_open( videoCodecContext, &mpeg1video_encoder ) < 0 ) {
printf("error opening context\n");
videoCodecContext = 0;
}
*/
/*
videoCodecContext->bit_rate = 400000;
videoCodecContext->gop_size = 10;
videoCodecContext->max_b_frames = 1;
*/
videoCodecContext->width = WIDTH;
videoCodecContext->height = HEIGHT;
videoCodecContext->frame_rate = 25;
videoCodecContext->frame_rate_base= 1;
videoCodecContext->pix_fmt=PIX_FMT_YUV420P;
videoCodecContext->codec_type = CODEC_TYPE_VIDEO;
videoCodecContext->codec_id = CODEC_ID_MPEG1VIDEO;
assert( avcodec_open( videoCodecContext, codec ) >= 0 );
printf("S %i\n", __LINE__);
}
void process( const Frame &frame )
{
printf("T %i\n", __LINE__);
YUVFrame *yuvFrame = (YUVFrame*)frame.data();
AVFrame *picture = yuvFrame->pic;
if ( !videoCodecContext ) {
printf("can't process video data without a context\n");
return;
}
Frame *f = getAvailableFrame();
FFMpegStreamPacket *ffmpeg = (FFMpegStreamPacket*)f->data();
AVPacket *packet = ffmpeg->packet;
printf("T %i\n", __LINE__);
// 160*120*4 = 76800
printf(" %i x %i %i %i %i \n", yuvFrame->width, yuvFrame->height, picture->linesize[0], picture->linesize[1], picture->linesize[2] );
AVFrame tmpPic;
if ( avpicture_alloc((AVPicture*)&tmpPic, PIX_FMT_YUV420P, yuvFrame->width, yuvFrame->height) < 0 )
printf("blah1\n");
img_convert((AVPicture*)&tmpPic, PIX_FMT_YUV420P, (AVPicture*)picture, yuvFrame->fmt,
yuvFrame->width, yuvFrame->height );
printf(" %i x %i %i %i %i \n", yuvFrame->width, yuvFrame->height, tmpPic.linesize[0], tmpPic.linesize[1], tmpPic.linesize[2] );
static int64_t pts = 0;
tmpPic.pts = AV_NOPTS_VALUE;
pts += 5000;
// int ret = avcodec_encode_video( videoCodecContext, (uchar*)av_malloc(1000000), 1024*256, &tmpPic );
packet->size = avcodec_encode_video( videoCodecContext, packet->data, packet->size, &tmpPic );
if ( videoCodecContext->coded_frame ) {
packet->pts = videoCodecContext->coded_frame->pts;
if ( videoCodecContext->coded_frame->key_frame )
packet->flags |= PKT_FLAG_KEY;
}
printf("T %i\n", __LINE__);
cerr << "encoded: " << packet->size << " bytes" << endl;
printf("T %i\n", __LINE__);
frame.deref();
SimpleModule::process( *f );
}
Frame* createNewFrame()
{
FFMpegStreamPacket *packet = new FFMpegStreamPacket;
packet->packet = new AVPacket;
packet->packet->data = new unsigned char[65536];
packet->packet->size = 65536;
packet->packet->pts = AV_NOPTS_VALUE;
packet->packet->flags = 0;
return new Frame( "FRAME_ID_MPEG1_VIDEO_PACKET", packet );
}
void reuseFrame( Frame *frame )
{
FFMpegStreamPacket *packet = (FFMpegStreamPacket*)frame->data();
packet->packet->size = 65536;
packet->packet->pts = AV_NOPTS_VALUE;
packet->packet->flags = 0;
//av_free_packet( packet->packet );
//delete packet->packet;
}
const char *name() { return "Mpeg Video Encoder"; }
Format inputFormat() { return "FRAME_ID_YUV_VIDEO_FRAME"; }
Format outputFormat() { return "FRAME_ID_MPEG1_VIDEO_PACKET"; }
bool isBlocking() { return true; }
private:
AVCodecContext *videoCodecContext;
};