1

I did a small program to encode raw images in h264rgb codec with ffmpeg. I use this codec because I needed to encode lossless rgb images (not possible with the classic h264 codec).

But now, I have a problem. I'm not able to decode the video generated with ffmpeg. I did a second small program for that, but I get a segfault when I reach the avcodec_decode_video2() function.

I did all the initialisation correctly. I didn't forget the avcodec_register_all() and av_init_packet() functions.

Here is the code for initialisation:

  _c = NULL;
  _frame_nb = 0;

  // Register all formats and codecs
  #pragma omp critical
  {
      avcodec_register_all();
  }

  _pkt = new AVPacket;
  av_init_packet(_pkt);  // a defaut de pouvoir ecrire : pkt = av_packet_alloc();

  if(!_pkt)
      exit(1);

    _codec = avcodec_find_encoder_by_name("libx264rgb");

  if (!_codec) {
      fprintf(stderr, "codec not found\n");
      exit(1);
  }

  _c = avcodec_alloc_context3(_codec);
  if (!_c) {
      fprintf(stderr, "Could not allocate video codec context\n");
      exit(1);
  }

  _c->debug = true;
  _c->pix_fmt =  (AVPixelFormat)AV_PIX_FMT_RGB24;
  _c->width = this->_headerCam[this->_currentCam]->iNbCol;
  _c->height = this->_headerCam[this->_currentCam]->iNbLine;

  _picture = av_frame_alloc();
  if (!_picture) {
      fprintf(stderr, "Could not allocate video _picture\n");
      exit(1);
  }

  _tmp_picture = av_frame_alloc();
  if (!_tmp_picture) {
      fprintf(stderr, "Could not allocate video _tmp_picture\n");
      exit(1);
  }


      _tmp_picture->format = (AVPixelFormat)AV_PIX_FMT_RGB24;
      _tmp_picture->width = this->_headerCam[this->_currentCam]->iNbCol;
      _tmp_picture->height = this->_headerCam[this->_currentCam]->iNbLine;
      _tmp_picture->linesize[0] = this->_headerCam[this->_currentCam]->iNbCol;

  /* open it */
  if (avcodec_open2(_c, _codec, NULL) < 0) {
      fprintf(stderr, "could not open codec\n");
      exit(1);
  }

And the decode function:

        _pkt->data = NULL;    // packet data will be allocated by the encoder
        _pkt->size = 0;

        unsigned char * inbuf;
        inbuf = (uint8_t*)av_malloc(w*h*3);

        //! read img size
        int size_img;
        fread(&size_img, sizeof(int), 1, this->_pFile);
        _pkt->size = fread(inbuf, 1, size_img, this->_pFile);

        _pkt->data = (unsigned char*)inbuf;

        if(_pkt->size)
        {
            len = avcodec_decode_video2(_c, _tmp_picture, &got_picture, _pkt);
            ...
        }

Any idea?

Furan
  • 21
  • 6

2 Answers2

0

+What the comment says, instead of inbuf = (uint8_t*)av_malloc(w*h*3); you should use this:

int buffer_size = av_image_get_buffer_size((AVPixelFormat)AV_PIX_FMT_RGB24, w, h, 1);
inbuf = (uint8_t*)av_malloc(buffer_size);

Because of portability for alignment and such issues.

And also fix this line _tmp_picture->linesize[0] = ... with this:
_tmp_picture->linesize[0] = av_image_get_linesize((AVPixelFormat)AV_PIX_FMT_RGB24, w, 0);

Hope that helps.

the kamilz
  • 1,860
  • 1
  • 15
  • 19
  • I tried your solution, but still I have a segmentation fault when I tried to decode the image. – Furan Feb 09 '18 at 08:46
  • Please check `size_img` and `_pkt->size` with `buffer_size` in my solution, they must match. – the kamilz Feb 09 '18 at 09:00
  • I displayed it and I get: buffer_size: 3686400 size_img: 2255123 _pkt->size: 2255123 – Furan Feb 09 '18 at 09:30
  • Chek my other post. I found a solution – Furan Feb 09 '18 at 09:35
  • For the buffer_size bigger than the pkt_size, I think it's normal as the buffer size corresponds to the size of a decoded image and _pkt->size corresponds to the size of an encoded image (so smaller). Thank you by the way for your answers. – Furan Feb 09 '18 at 09:46
0

Well, I finally found a beginning of answer: I used avcodec_find_encoder_by_name() instead of the avcodec_find_decoder_by_name()... It's certainly better if I want to decode data...

But now, I have the problem that _codec = avcodec_find_decoder_by_name("libx264rgb"); doesn't find the codec. But it works for _codec = avcodec_find_encoder_by_name("libx264rgb"); when I encoded my video.

EDIT : With _codec = avcodec_find_decoder(AV_CODEC_ID_H264); instead of _codec = avcodec_find_decoder_by_name("libx264rgb");, it is able to decode my video. It's weird but ok. Now, I hope I get lossless images.

EDIT2: Now, everything works! I got lossless decoded images with the AV_CODEC_ID_H264 decoder. To summarize, if you want to decode a video encoded with libx264rgb, you can use the classic AV_CODEC_ID_H264 codec.

Furan
  • 21
  • 6
  • Could you clarify in the answer if decoded frame is in YUV format or RGB? Makes sense to me that it will be in YUV requiring conversion back to RGB. Can you confirm? – shayst Dec 11 '19 at 12:19
  • I'm seeing a similar behavior. avcodec_find_encoder_by_name("vp8") returns null, but avcodec_find_decoder(AV_CODEC_ID_VP8) returns the decoder. Calling the name() method on that decoder returns "vp8". – Sergey Prigogin May 09 '22 at 21:22