You should set pts and maybe duration for pFrameYUV before you feed it into video encoder.
Alex On Friday, June 10, 2011, Jiří Novák <[email protected]> wrote: > Hello, > > I am trying to capture the X11 screen (using "x11grab") to the mpg output > format. This is first step (afterward i will need to add alsa audio), join it > into conteiner and at some point send it by socket. > > The problem I have is, that the mpg video I received is not syncronized, in > other words it looses its timing and is reproduced all in 2 seconds :(. > > Could anybody with experience of this please help me to correct this issue in > my code? > > Thank you very much, > Jiri Novak > > /*==========================================================================================================*/ > #include <iostream> > #include <stdio.h> > #include <assert.h> > #include <fstream> > > extern "C" { > #ifndef INT64_C > #define INT64_C(c) (c ## LL) > #define UINT64_C(c) (c ## ULL) > #endif > #include <libavcodec/avcodec.h> > #include <libswscale/swscale.h> > #include <libavformat/avformat.h> > #include <libavdevice/avdevice.h> > #include <libavfilter/avfilter.h> > } > > int main(int argc, char *argv[]) { > // register devices, filters and codecs > avdevice_register_all(); > avfilter_register_all(); > avcodec_init(); > avcodec_register_all(); > av_register_all(); > > // file format, format context > AVInputFormat *pInputFormat = av_find_input_format("x11grab"); > AVFormatContext *pFormatCtx = avformat_alloc_context(); > assert(pInputFormat != NULL && "format unrecognized - pInputFormat is > NULL!"); > assert(pFormatCtx != NULL && "format context could not be allocated - > pFormatCtx pointer is NULL!"); > > // format parameters > AVFormatParameters input_video_parameters, *ivp = &input_video_parameters; > memset(ivp, 0, sizeof(*ivp)); > ivp->prealloced_context = 1; > ivp->time_base= (AVRational){1,25}; > ivp->width = 1400; > ivp->height = 1050; > > // input_format_context, filename, input_format, buffer_size, > format_parameters > int ret = av_open_input_file(&pFormatCtx, ":0.0", pInputFormat, 0, ivp); > assert(ret >= 0 && "input video file could not be opened!"); > > // retrieve stream information > ret = av_find_stream_info(pFormatCtx); > assert(pFormatCtx >= 0 && "could not retrieve input video stream info!"); > > // dump information > dump_format(pFormatCtx, 0, ":0.0", 0); > > // find the first video stream > int videoStream=-1; > for(int i=0; i<pFormatCtx->nb_streams; i++) > if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { > videoStream=i; > break; > } > if(videoStream==-1) > return -1; // Didn't find a video stream > > // get a pointer to the codec context for the video stream > AVCodecContext *pCodecCtxDec = pFormatCtx->streams[videoStream]->codec; > > // find the decoder for the video stream > AVCodec *pCodecDec = avcodec_find_decoder(pCodecCtxDec->codec_id); > if(pCodecDec==NULL) { > fprintf(stderr, "Unsupported codec!\n"); > return -1; // Codec not found > } > > // open codec > if (avcodec_open(pCodecCtxDec, pCodecDec)<0) > return -1; // Could not open codec > > // alocate codec context > AVCodecContext *pCodecCtxEnc = avcodec_alloc_context(); > assert(pCodecCtxEnc != NULL && "pCodecCtxEnc pointer is null!"); > > // put sample parameters > pCodecCtxEnc->bit_rate = 400000; > pCodecCtxEnc->width = 1400; > pCodecCtxEnc->height = 1050; > pCodecCtxEnc->time_base= (AVRational){1,25}; > pCodecCtxEnc->gop_size = 10; > pCodecCtxEnc->max_b_frames=1; > pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P; > > // find MPEG4 encoder > AVCodec *pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO); > assert(pCodecEnc != NULL && "pCodecEnc pointer is null!"); > > // open the codec > int retval = avcodec_open(pCodecCtxEnc, pCodecEnc); > assert(retval == 0 && "could not open codec!"); > > // allocate video frame > AVFrame *pFrame = avcodec_alloc_frame(); > > // allocate an AVFrame structure > AVFrame *pFrameYUV=avcodec_alloc_frame(); > if(pFrameYUV==NULL) > return -1; > > // calculate the bytes needed for the output image and create buffer for > the output image > int nbytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtxEnc->width, > pCodecCtxEnc->height); > uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes*10); > > // assign appropriate parts of buffer to image planes in pFrameYUV > avpicture_fill((AVPicture *)pFrameYUV, outbuffer, PIX_FMT_YUV420P, > pCodecCtxDec->width, pCodecCtxDec->height); > > int frameFinished; > AVPacket packet; > > int i=0; > struct SwsContext *img_convert_ctx = NULL; > > FILE *f = fopen("output.mpg", "wb"); > int out_size; > > while (av_read_frame(pFormatCtx, &packet)>=0 && i<50) { > fflush(stdout); > > // is this a packet from the video stream > if(packet.stream_index==videoStream) { > // Decode video frame > avcodec_decode_video2(pCodecCtxDec, pFrame, &frameFinished, &packet); > > // Did we get a video frame? > if(frameFinished) { > if (img_convert_ctx == NULL) { > img_convert_ctx = sws_getContext(pCodecCtxDec->width, > pCodecCtxDec->height, PIX_FMT_BGRA, pCodecCtxEnc->width, > pCodecCtxEnc->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); > > if (img_convert_ctx == NULL) > std::cerr << "Error" << std::endl; > } > sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, > pCodecCtxEnc->height, pFrameYUV->data, pFrameYUV->linesize); > > out_size = avcodec_encode_video(pCodecCtxEnc, outbuffer, nbytes, > pFrameYUV); > //printf("write frame %3d (size=%5d)\n", i, out_size); > fwrite(outbuffer, 1, out_size, f); > } > } > > // Free the packet that was allocated by av_read_frame > av_free_packet(&packet); > i++; > } > > //get the delayed frames > for(; out_size; i++) { > fflush(stdout); > out_size = avcodec_encode_video(pCodecCtxEnc, outbuffer, nbytes, NULL); > //printf("write frame %3d (size=%5d)\n", i, out_size); > fwrite(outbuffer, 1, out_size, f); > } > > // add sequence end code to have a real mpeg file > outbuffer[0] = 0x00; > outbuffer[1] = 0x00; > outbuffer[2] = 0x01; > outbuffer[3] = 0xb7; > fwrite(outbuffer, 1, 4, f); > fclose(f); > > return 0; > } > > _______________________________________________ Libav-user mailing list [email protected] http://ffmpeg.org/mailman/listinfo/libav-user
