[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