[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