[Libav-user] Capturing X11 screen into mpg

Jiří Novák novak.jirik at gmail.com
Fri Jun 10 20:24:26 CEST 2011


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



More information about the Libav-user mailing list