Newer
Older
Import / research / pipeline / Modules / MpegEncodeModule.cpp


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;
};