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
这个函数的作用其实是将AVFrame
跟m_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
传进来之后就打酱油坐了个赋值。
网友评论