调用avcodec_encode_video时的EXC_BAD_ACCESS

发布于 2024-09-03 05:25:10 字数 1653 浏览 6 评论 0原文

我有一个 Objective-C 类(尽管我不认为这是特定于 Obj-C 的任何东西),我用它从一系列 CGImage 中将视频写入磁盘。 (我在顶部使用的获取像素数据的代码直接来自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

然后我在avcodec_encode_video处获得EXC_BAD_ACCESS。不确定它是否相关,但大部分代码来自 api-example.c。我正在使用 XCode,在 Snow Leopard 上编译 armv6/armv7。

预先非常感谢您的帮助!

I have an Objective-C class (although I don't believe this is anything Obj-C specific) that I am using to write a video out to disk from a series of CGImages. (The code I am using at the top to get the pixel data comes right from Apple: http://developer.apple.com/mac/library/qa/qa2007/qa1509.html). I successfully create the codec and context - everything is going fine until it gets to avcodec_encode_video, when I get EXC_BAD_ACCESS. I think this should be a simple fix, but I just can't figure out where I am going wrong.

I took out some error checking for succinctness. 'c' is an AVCodecContext*, which is created successfully.

-(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++;
}

I have stepped through it dozens of times. Here are some numbers...

  1. dataLength = 408960
  2. picture_buff = 0x5c85000
  3. picture->data[0] = 0x5c85000 -- which I take to mean that avpicture_fill worked...
  4. outbuf_size = 408960

and then I get EXC_BAD_ACCESS at avcodec_encode_video. Not sure if it's relevant, but most of this code comes from api-example.c. I am using XCode, compiling for armv6/armv7 on Snow Leopard.

Thanks so much in advance for help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不语却知心 2024-09-10 05:25:10

我这里没有足够的信息来指出确切的错误,但我认为问题在于输入图片包含的数据少于 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),则输入缓冲区的大小为 width*height*1.5,但 avpicture_fill()预计大小为宽度*高度*4。

因此,检查输入/输出几何图形和像素格式应该可以找到错误的原因。如果没有帮助,我建议您首先尝试编译 i386。为 iPhone 正确编译 FFMPEG 是很棘手的。

I have not enough information here to point to the exact error, but I think that the problem is that the input picture contains less data than avcodec_encode_video() expects:

avpicture_fill() only sets some pointers and numeric values in the AVFrame structure. It does not copy anything, and does not check whether the buffer is large enough (and it cannot, since the buffer size is not passed to it). It does something like this (copied from ffmpeg source):

    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;

Note that the width and height is passed from the variable "c" (the AVCodecContext, I assume), so it may be larger than the actual size of the input frame.

It is also possible that the width/height is good, but the pixel format of the input frame is different from what is passed to avpicture_fill(). (note that the pixel format also comes from the AVCodecContext, which may differ from the input). For example, if c->pix_fmt is RGBA and the input buffer is in YUV420 format (or, more likely for iPhone, a biplanar YCbCr), then the size of the input buffer is width*height*1.5, but avpicture_fill() expects the size of width*height*4.

So checking the input/output geometry and pixel formats should lead you to the cause of the error. If it does not help, I suggest that you should try to compile for i386 first. It is tricky to compile FFMPEG for the iPhone properly.

心房的律动 2024-09-10 05:25:10

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

Does the codec you are encoding support the RGB color space? You may need to use libswscale to convert to I420 before encoding. What codec are you using? Can you post the code where you initialize your codec context?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文