[Libav-user] Capturing X11 screen into mpg

Alex Cohn alexcohn at netvision.net.il
Fri Jun 10 23:44:56 CEST 2011


You (and yours truly, actually) should probably study deeply
http://dranger.com/ffmpeg/tutorial05.html. Anyway, what does ffprobe
say about your output.mpg file? Does it recognize the frame rate? IIRC
it will not know duration for this format.

Alex

On Fri, Jun 10, 2011 at 9:24 PM, Jiří Novák <novak.jirik at gmail.com> wrote:
> Thank you Alex!
>
> couldn't you please show me how? I am absolute begginer with libavcodec and
> with the lack of documentation and version differences I am more fighting
> than enjoying with this library... :(
>
> Jiri
>
> On 06/10/2011 03:22 PM, Alex Cohn wrote:
>>
>> 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<jiri.novak at petriny.net>  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
>> Libav-user at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/libav-user
>
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/libav-user
>


More information about the Libav-user mailing list