调用avcodec_encode_video时EXC_BAD_ACCESS

时间:2010-05-28 19:21:56

标签: iphone c objective-c ffmpeg libavcodec

我有一个Objective-C类(虽然我不相信这是Obj-C特有的)我用来从一系列CGImages中将视频写入磁盘。 (我在顶部用来获取像素数据的代码来自Apple:http://developer.apple.com/mac/library/qa/qa2007/qa1509.html)。我成功地创建了编解码器和上下文 - 一切正常,直到它获得avcodec_encode_video,当我得到EXC_BAD_ACCESS时。我认为这应该是一个简单的修复,但我无法弄清楚我哪里出错。

我拿出一些错误检查以确定简洁性。 'c'是AVCodecContext *,已成功创建。

-(void)addFrame:(CGImageRef)img
{
  CFDataRef bitmapData = CGDataProviderCopyData(CGImageGetDataProvider(img));
  long dataLength = CFDataGetLength(bitmapData);
  uint8_t* picture_buff = (uint8_t*)malloc(dataLength);
  CFDataGetBytes(bitmapData, CFRangeMake(0, dataLength), picture_buff);

  AVFrame *picture = avcodec_alloc_frame();
  avpicture_fill((AVPicture*)picture, picture_buff, c->pix_fmt, c->width, c->height);

  int outbuf_size = avpicture_get_size(c->pix_fmt, c->width, c->height);
  uint8_t *outbuf = (uint8_t*)av_malloc(outbuf_size);

  out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); // ERROR occurs here
  printf("encoding frame %3d (size=%5d)\n", i, out_size);
  fwrite(outbuf, 1, out_size, f);

  CFRelease(bitmapData);
  free(picture_buff);
  free(outbuf);
  av_free(picture);
  i++;
}

我已经介入了几十次。这里有一些数字......

  1. dataLength = 408960
  2. picture_buff = 0x5c85000
  3. picture-> data [0] = 0x5c85000 - 我认为avpicture_fill有效......
  4. outbuf_size = 408960
  5. 然后我在avcodec_encode_video上获得了EXC_BAD_ACCESS。不确定它是否相关,但大部分代码来自api-example.c。我正在使用XCode,在Snow Leopard上编译armv6 / armv7。

    非常感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

我这里没有足够的信息指出确切的错误,但我认为问题是输入图片包含的数据少于avcodec_encode_video()所期望的:

avpicture_fill()仅在AVFrame结构中设置一些指针和数值。它不会复制任何东西,也不会检查缓冲区是否足够大(并且它不能,因为缓冲区大小没有传递给它)。它做了类似的事情(从ffmpeg源复制):

    size = picture->linesize[0] * height;
    picture->data[0] = ptr;
    picture->data[1] = picture->data[0] + size;
    picture->data[2] = picture->data[1] + size2;
    picture->data[3] = picture->data[1] + size2 + size2;

请注意,宽度和高度是从变量“c”(我假设为AVCodecContext)传递的,因此它可能大于输入帧的实际大小。

宽度/高度也可能是好的,但输入帧的像素格式与传递给avpicture_fill()的像素格式不同。 (请注意,像素格式也来自AVCodecContext,它可能与输入不同)。例如,如果c-> pix_fmt是RGBA且输入缓冲区是YUV420格式(或者更可能是iPhone,双平面YCbCr),那么输入缓冲区的大小是宽*高* 1.5,但是avpicture_fill()期望宽度*高度* 4的大小。

因此,检查输入/输出几何和像素格式应该会导致错误原因。如果它没有帮助,我建议您首先尝试编译i386。正确编译适用于iPhone的FFMPEG非常棘手。

答案 1 :(得分:0)

您编码的编解码器是否支持RGB色彩空间?您可能需要在编码之前使用libswscale转换为I420。您使用的编解码器是什么?您可以在初始化编解码器上下文的位置发布代码吗?

答案 2 :(得分:0)