FFmpeg iOS从AVFrame获取UIImage

时间:2019-03-04 11:23:10

标签: ios objective-c ffmpeg

我无法从正在读取到iOS FFmpeg项目的框架中获取UIImage。我需要能够读取框架,然后将其转换为UIImage以便在UIImageView中显示框架。我的代码似乎在阅读框架,但是我对如何转换它们迷失了,因为有关如何执行此操作的文档很少。有人可以帮忙吗?

while (!finished) {
    if (av_read_frame(_formatContext, &packet) >= 0) {
        if (packet.stream_index == _videoStream) {
            int ret = avcodec_send_packet(_codecContext, &packet);
            if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                printf("av_codec_send_packet error ");
            }
            while (ret >= 0) {
                ret = avcodec_receive_frame(_codecContext, _frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    printf("avcodec_receive_frame error ");
                }



                finished = true;
            }
        }
        av_packet_unref(&packet);
    }
}

1 个答案:

答案 0 :(得分:0)

您应该了解rgb和yuv等像素格式。视频几乎总是使用yuv格式(例如yuv420p)。然后研究AVFrame结构,这里有一些信息:

AVFormat.format:当前帧的像素格式,即AV_PIX_FMT_YUV420P
AVFormat.width:当前帧的水平长度(因此宽度)单位:像素
AVFormat.height:当前帧的垂直长度(因此高度)单位:像素

现在您可能要问的实际帧缓冲区在哪里,它在AVFormat.data[n]中 n可以为0-3。根据格式,仅第一个可能包含整个框架或全部四个框架。即yuv420p使用0、1和2。可以通过读取相应的AVFormat.linesize[n]值来获得其线距(也称为步幅)。 至于yuv420p:
data[0]是Y平面
data[1]是U平面
data[2]是V平面
如果将linesize[0]AVFrame.height相乘,您将获得该平面的大小(Y)作为字节数。

我不知道UIImage结构(或其任何形式),如果它需要RGB之类的特定格式,则需要使用swscale将AVFrame转换为该格式。 以下是一些示例:https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/scaling_video.c

在libav(ffmpeg)中,缩放(调整大小)和像素格式转换是通过相同的功能完成的。

希望这些帮助。