Hello,<br><br>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.<br>
<br>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 :(.<br><br>Could anybody with experience of this please help me to correct this issue in my code?<br>
<br>Thank you very much,<br>Jiri Novak<br><br>/*==========================================================================================================*/<br>#include <iostream><br>#include <stdio.h><br>#include <assert.h><br>
#include <fstream><br><br>extern "C" {<br>#ifndef INT64_C<br>#define INT64_C(c) (c ## LL)<br>#define UINT64_C(c) (c ## ULL)<br>#endif<br>#include <libavcodec/avcodec.h><br>#include <libswscale/swscale.h><br>
#include <libavformat/avformat.h><br>#include <libavdevice/avdevice.h><br>#include <libavfilter/avfilter.h><br>}<br><br>int main(int argc, char *argv[]) {<br>  // register devices, filters and codecs<br>
  avdevice_register_all();<br>  avfilter_register_all();<br>  avcodec_init();<br>  avcodec_register_all();<br>  av_register_all();<br>  <br>  // file format, format context<br>  AVInputFormat *pInputFormat = av_find_input_format("x11grab");<br>
  AVFormatContext *pFormatCtx = avformat_alloc_context();  <br>  assert(pInputFormat != NULL && "format unrecognized - pInputFormat is NULL!");<br>  assert(pFormatCtx != NULL && "format context could not be allocated - pFormatCtx pointer is NULL!");<br>
<br>  // format parameters<br>  AVFormatParameters input_video_parameters, *ivp = &input_video_parameters;<br>  memset(ivp, 0, sizeof(*ivp));<br>  ivp->prealloced_context = 1;<br>  ivp->time_base= (AVRational){1,25};<br>
  ivp->width = 1400;<br>  ivp->height = 1050;<br>  <br>  // input_format_context, filename, input_format, buffer_size, format_parameters<br>  int ret = av_open_input_file(&pFormatCtx, ":0.0", pInputFormat, 0, ivp);<br>
  assert(ret >= 0 && "input video file could not be opened!");<br><br>  // retrieve stream information<br>  ret = av_find_stream_info(pFormatCtx);<br>  assert(pFormatCtx >= 0 && "could not retrieve input video stream info!");<br>
<br>  // dump information<br>  dump_format(pFormatCtx, 0, ":0.0", 0);<br>  <br>  // find the first video stream<br>  int videoStream=-1;<br>  for(int i=0; i<pFormatCtx->nb_streams; i++)<br>    if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {<br>
      videoStream=i;<br>      break;<br>    }<br>  if(videoStream==-1)<br>    return -1; // Didn't find a video stream<br>  <br>  // get a pointer to the codec context for the video stream<br>  AVCodecContext *pCodecCtxDec = pFormatCtx->streams[videoStream]->codec;<br>
  <br>  // find the decoder for the video stream  <br>  AVCodec *pCodecDec = avcodec_find_decoder(pCodecCtxDec->codec_id);<br>  if(pCodecDec==NULL) {<br>    fprintf(stderr, "Unsupported codec!\n");<br>    return -1; // Codec not found<br>
  }<br>  <br>  // open codec<br>  if (avcodec_open(pCodecCtxDec, pCodecDec)<0)<br>    return -1; // Could not open codec<br><br>  // alocate codec context<br>  AVCodecContext *pCodecCtxEnc = avcodec_alloc_context();<br>
  assert(pCodecCtxEnc != NULL && "pCodecCtxEnc pointer is null!");<br>  <br>  // put sample parameters<br>  pCodecCtxEnc->bit_rate = 400000;<br>  pCodecCtxEnc->width = 1400;<br>  pCodecCtxEnc->height = 1050;<br>
  pCodecCtxEnc->time_base= (AVRational){1,25};<br>  pCodecCtxEnc->gop_size = 10;<br>  pCodecCtxEnc->max_b_frames=1;<br>  pCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;<br>  <br>  // find MPEG4 encoder<br>  AVCodec *pCodecEnc = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO);<br>
  assert(pCodecEnc != NULL && "pCodecEnc pointer is null!");<br>  <br>  // open the codec<br>  int retval = avcodec_open(pCodecCtxEnc, pCodecEnc);<br>  assert(retval == 0 && "could not open codec!");<br>
<br>  // allocate video frame<br>  AVFrame *pFrame = avcodec_alloc_frame();<br><br>  // allocate an AVFrame structure<br>  AVFrame *pFrameYUV=avcodec_alloc_frame();<br>  if(pFrameYUV==NULL)<br>    return -1;<br>  <br>  // calculate the bytes needed for the output image and create buffer for the output image<br>
  int nbytes = avpicture_get_size(PIX_FMT_YUV420P, pCodecCtxEnc->width, pCodecCtxEnc->height);<br>  uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes*10);<br><br>  // assign appropriate parts of buffer to image planes in pFrameYUV<br>
  avpicture_fill((AVPicture *)pFrameYUV, outbuffer, PIX_FMT_YUV420P, pCodecCtxDec->width, pCodecCtxDec->height); <br><br>  int frameFinished;<br>  AVPacket packet;<br><br>  int i=0;<br>  struct SwsContext *img_convert_ctx = NULL;<br>
<br>  FILE *f = fopen("output.mpg", "wb");<br>  int out_size;<br><br>  while (av_read_frame(pFormatCtx, &packet)>=0 && i<50) {<br>    fflush(stdout);<br><br>    // is this a packet from the video stream<br>
    if(packet.stream_index==videoStream) {<br>      // Decode video frame<br>      avcodec_decode_video2(pCodecCtxDec, pFrame, &frameFinished, &packet);<br>      <br>      // Did we get a video frame?<br>      if(frameFinished) {<br>
    if (img_convert_ctx == NULL) {<br>      img_convert_ctx = sws_getContext(pCodecCtxDec->width, pCodecCtxDec->height, PIX_FMT_BGRA, pCodecCtxEnc->width, pCodecCtxEnc->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);<br>
      <br>      if (img_convert_ctx == NULL)<br>        std::cerr << "Error" << std::endl;<br>    }<br>    sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtxEnc->height, pFrameYUV->data, pFrameYUV->linesize);<br>
    <br>    out_size = avcodec_encode_video(pCodecCtxEnc, outbuffer, nbytes, pFrameYUV);<br>    //printf("write frame %3d (size=%5d)\n", i, out_size);<br>    fwrite(outbuffer, 1, out_size, f);<br>      }<br>    }<br>
    <br>    // Free the packet that was allocated by av_read_frame<br>    av_free_packet(&packet);<br>    i++;<br>  }<br><br>  //get the delayed frames<br>  for(; out_size; i++) {<br>    fflush(stdout);<br>    out_size = avcodec_encode_video(pCodecCtxEnc, outbuffer, nbytes, NULL);<br>
    //printf("write frame %3d (size=%5d)\n", i, out_size);<br>    fwrite(outbuffer, 1, out_size, f);<br>  }<br><br>  // add sequence end code to have a real mpeg file<br>  outbuffer[0] = 0x00;<br>  outbuffer[1] = 0x00;<br>
  outbuffer[2] = 0x01;<br>  outbuffer[3] = 0xb7;<br>  fwrite(outbuffer, 1, 4, f);<br>  fclose(f);<br>  <br>  return 0;<br>}<br><br>