1

First, sorry for my english. When I decode h264 720p in ardrone2.0 my output is black and I cant see anything.

I have try to change the value of pCodecCtx->pix_fmt = AV_PIX_FMT_BGR24; to pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P; and the value of pCodecCtxH264->pix_fmt = AV_PIX_FMT_BGR24; to pCodecCtxH264->pix_fmt = AV_PIX_FMT_YUV420P; but my program crash. What am I doing wrong?. Thank you, see part of my code:

av_register_all();
avcodec_register_all();
avformat_network_init();

// 1.2. Open video file
if(avformat_open_input(&pFormatCtx, drone_addr, NULL, NULL) != 0) {
  mexPrintf("No conecct with Drone");
  EndVideo();
  return;
}

pCodec    = avcodec_find_decoder(AV_CODEC_ID_H264);

pCodecCtx = avcodec_alloc_context3(pCodec);
pCodecCtx->pix_fmt = AV_PIX_FMT_BGR24;
pCodecCtx->skip_frame = AVDISCARD_DEFAULT;
pCodecCtx->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
pCodecCtx->err_recognition = AV_EF_CAREFUL;
pCodecCtx->skip_loop_filter = AVDISCARD_DEFAULT;
pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->codec_id = AV_CODEC_ID_H264;
pCodecCtx->skip_idct = AVDISCARD_DEFAULT;
pCodecCtx->width = 1280;
pCodecCtx->height = 720;

pCodecH264 = avcodec_find_decoder(AV_CODEC_ID_H264);
pCodecCtxH264 = avcodec_alloc_context3(pCodecH264);


pCodecCtxH264->pix_fmt = AV_PIX_FMT_BGR24;
pCodecCtxH264->skip_frame = AVDISCARD_DEFAULT;
pCodecCtxH264->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
pCodecCtxH264->err_recognition = AV_EF_CAREFUL;
pCodecCtxH264->skip_loop_filter = AVDISCARD_DEFAULT;
pCodecCtxH264->workaround_bugs = FF_BUG_AUTODETECT;
pCodecCtxH264->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtxH264->codec_id = AV_CODEC_ID_H264;
pCodecCtxH264->skip_idct = AVDISCARD_DEFAULT;

if(avcodec_open2(pCodecCtxH264, pCodecH264, &optionsDict) < 0)
{
   mexPrintf("Error opening H264 codec");
   return ;
}

pFrame_BGR24 = av_frame_alloc();


if(pFrame_BGR24 == NULL) {
   mexPrintf("Could not allocate pFrame_BGR24\n");
   return ;
}

// Determine required buffer size and allocate buffer

buffer_BGR24 = 
(uint8_t *)av_mallocz(av_image_get_buffer_size(AV_PIX_FMT_BGR24, 
pCodecCtx->width, ((pCodecCtx->height == 720) ? 720 : pCodecCtx->height) * 
sizeof(uint8_t)*3,1));

// Assign buffer to image planes

av_image_fill_arrays(pFrame_BGR24->data, pFrame_BGR24->linesize,
buffer_BGR24,AV_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height,1);

// format conversion context
pConvertCtx_BGR24 = sws_getContext(pCodecCtx->width, pCodecCtx->height, 
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,  AV_PIX_FMT_BGR24, 
                                 SWS_BILINEAR | SWS_ACCURATE_RND, 0, 0, 0);

// 1.6. get video frames
pFrame = av_frame_alloc();

av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
}

//Captura un frame
void video::capture(mxArray *plhs[]) {

  if(av_read_frame(pFormatCtx, &packet) < 0){
      mexPrintf("Error al leer frame");
      return;
  }
   do {
       do {
          rest = avcodec_send_packet(pCodecCtxH264, &packet);
       } while(rest == AVERROR(EAGAIN));

       if(rest == AVERROR_EOF || rest == AVERROR(EINVAL)) {
                printf("AVERROR(EAGAIN): %d, AVERROR_EOF: %d, 
                AVERROR(EINVAL): %d\n", AVERROR(EAGAIN), AVERROR_EOF, 
                AVERROR(EINVAL));
            printf("fe_read_frame: Frame getting error (%d)!\n", rest);
            return;
       }

       rest = avcodec_receive_frame(pCodecCtxH264, pFrame);
   } while(rest == AVERROR(EAGAIN));

   if(rest == AVERROR_EOF || rest == AVERROR(EINVAL)) {

    // An error or EOF occured,index break out and return what
    // we have so far.
      printf("AVERROR(EAGAIN): %d, AVERROR_EOF: %d, AVERROR(EINVAL): %d\n", 
      AVERROR(EAGAIN), AVERROR_EOF, AVERROR(EINVAL));
        printf("fe_read_frame: EOF or some othere decoding error (%d)!\n", 
        rest);
        return;
   }


   // 2.1.1. convert frame to GRAYSCALE [or BGR] for OpenCV
   sws_scale(pConvertCtx_BGR24,   (const uint8_t* const*)pFrame->data, 
       pFrame->linesize, 0,pCodecCtx->height,   pFrame_BGR24->data,   
             pFrame_BGR24->linesize);
//}
   av_packet_unref(&packet);
   av_init_packet(&packet);
   mwSize dims[] = {(pCodecCtx->width)*((pCodecCtx->height == 720) ? 720 : 
   pCodecCtx->height)*sizeof(uint8_t)*3};
   plhs[0] = mxCreateNumericArray(1,dims,mxUINT8_CLASS, mxREAL);
    //plhs[0]=mxCreateDoubleMatrix(pCodecCtx->height,pCodecCtx-
    >width,mxREAL);
   point=mxGetPr(plhs[0]);
   memcpy(point, pFrame_BGR24->data[0],(pCodecCtx->width)*(pCodecCtx-
    >height)*sizeof(uint8_t)*3);
}
  • You are not decoding the frame. – szatmary Dec 05 '17 at 14:03
  • I have to say that when I change the resolution to 640x360 I can obtain the frame with `AV_PIX_FMT_YUV420P`, but Ardrone can to send high quality video and I dont understand because the code works with 640x360 and not work with 1280x720 – José Marqueses Saxo Dec 05 '17 at 16:57

1 Answers1

0

Go to debugger and see your memcpy. I am not sure if it works for all dimensions that you want. Also, there may be more memory problems. For example, try to see what is the value of buffer_BGR24 and pFrame. I bet that sometimes, they do not return right values. Check them out in the code.

VladP
  • 529
  • 3
  • 15
  • The problem is in sws_scale function (`sws_scale(pConvertCtx_BGR24, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0,pCodecCtx->height, pFrame_BGR24->data, pFrame_BGR24->linesize);`). The code crash in this point. This works with low resolution (640x360) but crash with high resolution (1280x720). – José Marqueses Saxo Dec 06 '17 at 11:55
  • It seems that you have 6 arguments when calling sws_scale, and I can see that the function takes 7 arguments: int sws_scale(SwsContext *c, uint8_t *src, int srcStride[], int srcSliceY, int srcSliceH, uint8_t dst[], int dstStride[], as per http://dranger.com/ffmpeg/functions.html#sws_scale. Please, go to debugger and check the input to this function. Sometimes, the context is changed automatically to values that you are not expecting. That is what the library does. – VladP Dec 06 '17 at 15:13