Hello,
I need to encode a video with the Xvid codec, but run into the problem
that avcodec_encode_video() keeps returning -1.
Since I work on Windows, I compiled the Xvid codec and than ffmpeg and
avcodec.lib with mingw using the following configure:

$ ./configure --enable-shared --enable-memalign-hack
--prefix=../../libffmpeg.xvid --extra-ldflags="-Wl,-add-std
call-alias,-L../../libxvid/lib" --extra-cflags="-I../../libxvid/include"
--enable-libxvid --enable-gpl --enable-
encoder=CODEC_ID_XVID

Using ffmpeg.exe, I'm able to convert an mpeg-video to a Xvid-coded avi, so
the generated avcodec.lib seems to support Xvid.

Than I build a class based on output_example.c to write a Xvid-coded video
directly. Using any other codec (e.g. CODEC_ID_MPEG4) works fine, but
setting
tAVOutputFormat->video_codec = CODEC_ID_XVID results in
avcodec_encode_video() returning -1.
I assume that I have to set other values in the AVCodecContext to make the
codec work,  but I didn't find any documentation or example on it.

Regards,
Torsten

Here is the relevant code:


int CMpegEncoderFFMPEG::init(
  int pBitrate,
  int pWidth,
  int pHeight,
  int pFramesPerSecond,
  bool pWriteFile )
{
  // initialize libavcodec, and register all codecs and formats
  avcodec_init();
avcodec_register_all();
  av_register_all();

  const char* tFilename = "test.avi";
  mWriteFile = pWriteFile;

  // auto detect the output format from the name; default is mpeg
  AVOutputFormat* tAVOutputFormat = guess_format(NULL, tFilename, NULL);
  if( !tAVOutputFormat )
  {
    printf("Could not deduce output format from file extension: using
MPEG.\n");
    tAVOutputFormat = guess_format("mpeg", NULL, NULL);
  }
  if( !tAVOutputFormat )
  {
    fprintf(stderr, "Could not find suitable output format\n");
    return 0;
  }

  // the codec is determined implicitly by the format
  // mpeg -> CODEC_ID_MPEG1VIDEO (1)
  // mp4 -> CODEC_ID_MPEG4 (13)
  // avi -> CODEC_ID_MPEG4 (13)
  // set XVID codec explicitly
  tAVOutputFormat->video_codec = CODEC_ID_XVID;

  // allocate the output media context
  mAVFormatContext = avformat_alloc_context();
  if( !mAVFormatContext )
  {
    fprintf(stderr, "Memory error\n");
    return 0;
  }
  mAVFormatContext->oformat = tAVOutputFormat;
  sprintf_s( mAVFormatContext->filename, sizeof(mAVFormatContext->filename),
"%s", tFilename );

  // add the audio and video streams using the default format codecs and
initialize the codecs
  if( tAVOutputFormat->video_codec != CODEC_ID_NONE )
    mVideoStream = addVideoStream( mAVFormatContext,
tAVOutputFormat->video_codec, pBitrate, pWidth, pHeight, pFramesPerSecond );

  if( tAVOutputFormat->audio_codec != CODEC_ID_NONE)
    mAudioStream = addAudioStream( mAVFormatContext,
tAVOutputFormat->audio_codec );

  // set the output parameters (must be done even if no parameters)
  if (av_set_parameters(mAVFormatContext, NULL) < 0)
  {
    fprintf(stderr, "Invalid output format parameters\n");
    return 0;
  }

  dump_format( mAVFormatContext, 0, tFilename, 1 );

  // now that all the parameters are set, we can open the audio and video
codecs and allocate the necessary encode buffers
  if( mVideoStream )
    openVideo( mAVFormatContext, mVideoStream );
  if( mAudioStream )
    openAudio( mAVFormatContext, mAudioStream );

  // open the output file
  if( mWriteFile )
  {
    if( url_fopen(&mAVFormatContext->pb, tFilename, URL_WRONLY) < 0 )
    {
      fprintf( stderr, "Could not open '%s'\n", tFilename );
      return 0;
    }
    // write the stream header, if any
    av_write_header(mAVFormatContext);
  }

  return 0;
}





AVStream* CMpegEncoderFFMPEG::addVideoStream(
  AVFormatContext *oc,
  int codec_id,
  int pBitrate,
  int pWidth,
  int pHeight,
  int pFramesPerSecond )
{
  AVStream *tAVStream = av_new_stream(oc, 0);
  if( !tAVStream )
  {
    fprintf(stderr, "Could not alloc stream\n");
    return 0;
  }

  AVCodecContext *c = tAVStream->codec;
  c->codec_id = (CodecID) codec_id;
  c->codec_type = CODEC_TYPE_VIDEO;
  // put sample parameters
  c->bit_rate = pBitrate;
  // resolution must be a multiple of two
  c->width = pWidth;
  c->height = pHeight;
  // time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented
  // for fixed-fps content, timebase should be 1/framerate and timestamp
increments should be identically 1
  c->time_base.den = pFramesPerSecond;
  c->time_base.num = 1;
  c->gop_size = 12; // emit one intra frame every twelve frames at most
  c->pix_fmt = STREAM_PIX_FMT;
  if (c->codec_id == CODEC_ID_MPEG2VIDEO)
  {
    // just for testing, we also add B frames
    c->max_b_frames = 2;
  }
  if (c->codec_id == CODEC_ID_MPEG1VIDEO)
  {
    // Needed to avoid using macroblocks in which some coeffs overflow.
    // This does not happen with normal video, it just happens here as
    // the motion of the chroma plane does not match the luma plane.
    c->mb_decision=2;
  }

  if (c->codec_id == CODEC_ID_XVID )
  {
    c->pix_fmt = PIX_FMT_YUV420P; // ???
  }

  // some formats want stream headers to be separate
  if(oc->oformat->flags & AVFMT_GLOBALHEADER)
    c->flags |= CODEC_FLAG_GLOBAL_HEADER;

  return tAVStream;
}




int CMpegEncoderFFMPEG::encodeVideoFrame(
  AVFormatContext* pAVFormatContext,
  AVStream *st )
{
  int tOutputSize;
  AVCodecContext *c = st->codec;

  if( pAVFormatContext->oformat->flags & AVFMT_RAWPICTURE )
  {
    // raw video case
    if( mWriteFile )
    {
      AVPacket pkt;
      av_init_packet(&pkt);
      pkt.flags |= PKT_FLAG_KEY;
      pkt.stream_index= st->index;
      pkt.data= (uint8_t *)mAVFrame;
      pkt.size= sizeof(AVPicture);
      int ret = av_interleaved_write_frame( pAVFormatContext, &pkt );
    }
  }
  else
  {
    // encode the image
    tOutputSize = avcodec_encode_video( c, mVideoOutputBuffer,
mVideoOutputBufferSize, mAVFrame );

    // if zero size, it means the image was buffered
    if( mWriteFile && tOutputSize>0 )
    {
      AVPacket pkt;
      av_init_packet(&pkt);
      if( c->coded_frame->pts != AV_NOPTS_VALUE )
        pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base,
st->time_base);
      if( c->coded_frame->key_frame )
        pkt.flags |= PKT_FLAG_KEY;
      pkt.stream_index = st->index;
      pkt.data = mVideoOutputBuffer;
      pkt.size = tOutputSize;
      int ret = av_interleaved_write_frame(pAVFormatContext, &pkt);
    }
  }

  mFrameCount++;
  return tOutputSize;
}
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to