美文网首页
ffmpeg播放视频的部分方法解析

ffmpeg播放视频的部分方法解析

作者: YocnZhao | 来源:发表于2021-08-24 19:38 被阅读0次

    ffmpeg播放视频的部分方法解析

    • ANativeWindow_Buffer->stride

    The number of *pixels* that a line in the buffer takes in memory. This may be >= width.
    图像的一行在内存里占的空间,做了对齐,可能比宽度大一些。比如宽高为544 * 960的视频下stride可能为576,所以在向m_NativeWindowBuffer.bits中拷贝图像数据的时候需要考虑此步长数据,每次向m_NativeWindowBuffer.bits中拷贝544个bytes,需要占据576个bytes空间。

    也就是:

    memcpy(dstBuffer + i * 576 * x, srcBuffer + i * 544 * x, 544 * x);
    

    x:如果是RGBA_8888格式,x=4,如果是RGB_565,则x=2.

    • AVFrame->linesize的赋值

    linesize存储的是图像的尺寸,不是一个固定值,是根据格式来的。
    一个宽高为544 * 960的视频,在常见的格式下:

    \ linesize[0] linesize[1] linesize[2] linesize[3]
    YUV420P 544 272 272 0
    RGB_565 1088 0 0 0
    RGBA_8888 2176 0 0 0
    • av_image_fill_arrays的作用

    在使用的时候一般是这样:

        int bufferSize = av_image_get_buffer_size(AV_PIX_FMT_RGB565LE, m_VideoWidth, m_VideoHeight, 1);
        auto *m_FrameBuffer = (uint8_t *) av_malloc(bufferSize * sizeof(uint8_t));
        av_image_fill_arrays(m_RGBAFrame->data, m_RGBAFrame->linesize, m_FrameBuffer,
                             AV_PIX_FMT_RGB565LE, m_VideoWidth, m_VideoHeight, 1);
    
    

    根据需要的显示类型和视频的宽高计算出需要的缓冲区bufferSize的大小,申请一块bufferSize大小的内存,然后使用av_image_fill_arrays,然后传入了我们拿来接收配置的的m_RGBAFrame和新申请的m_FrameBuffer
    这个函数的作用其实是将AVFramem_FrameBuffer绑定在了一起,然后设置了对应的data和linesize数据。
    我们可以查看这个函数的源码:

    int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],
                             const uint8_t *src, enum AVPixelFormat pix_fmt,
                             int width, int height, int align)
    {
        int ret, i;
    
        ret = av_image_check_size(width, height, 0, NULL);
        if (ret < 0)
            return ret;
    
        ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);
        if (ret < 0)
            return ret;
    
        for (i = 0; i < 4; i++)
            dst_linesize[i] = FFALIGN(dst_linesize[i], align);
    
        return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
    }
    
    int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height,
                               uint8_t *ptr, const int linesizes[4])
    {
        int i, ret;
        ptrdiff_t linesizes1[4];
        size_t sizes[4];
    
        memset(data     , 0, sizeof(data[0])*4);
    
        for (i = 0; i < 4; i++)
            linesizes1[i] = linesizes[i];
    
        ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, linesizes1);
        if (ret < 0)
            return ret;
    
        ret = 0;
        for (i = 0; i < 4; i++) {
            if (sizes[i] > INT_MAX - ret)
                return AVERROR(EINVAL);
            ret += sizes[i];
        }
    
        data[0] = ptr;
        for (i = 1; i < 4 && sizes[i]; i++)
            data[i] = data[i - 1] + sizes[i - 1];
    
        return ret;
    }
    

    发现其实把ptr也就是src赋值给了data[0],其实m_FrameBuffer传进来之后就打酱油坐了个赋值。

    AVFrame中data与linesize关系

    相关文章

      网友评论

          本文标题:ffmpeg播放视频的部分方法解析

          本文链接:https://www.haomeiwen.com/subject/bseeiltx.html