[Libav-user] Capturing X11 screen into mpg
Jiří Novák
jiri.novak at petriny.net
Fri Jun 10 17:57:02 CEST 2011
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;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20110610/eb7582b5/attachment.html>
More information about the Libav-user
mailing list