| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- #ifndef VFRAME_H
- #define VFRAME_H
- #include <QObject>
- #include <stdlib.h>
- #include <string.h>
- #include "ffmpeg_compat.h"
- class VideoFrame
- {
- public:
- // 从各平面数据+步幅构建,内部拷贝成为自有连续缓冲区
- VideoFrame(AVPixelFormat fmt,
- uint32_t pixelW,
- uint32_t pixelH,
- uint8_t* const data[4],
- const int linesize[4])
- : m_buffer(nullptr)
- , m_bufSize(0)
- , m_format(fmt)
- , m_pixelW(pixelW)
- , m_pixelH(pixelH)
- {
- allocateAndCopy(data, linesize);
- }
- // 从连续内存基址构建(假定按 align=1 的 FFmpeg 平面布局),用于快速拷贝
- VideoFrame(AVPixelFormat fmt, uint32_t pixelW, uint32_t pixelH, const uint8_t* base)
- : m_buffer(nullptr)
- , m_bufSize(0)
- , m_format(fmt)
- , m_pixelW(pixelW)
- , m_pixelH(pixelH)
- {
- int needed = av_image_get_buffer_size(fmt, pixelW, pixelH, 1);
- if (needed <= 0) return;
- m_buffer = (uint8_t*)malloc(needed);
- if (!m_buffer) return;
- m_bufSize = needed;
- memcpy(m_buffer, base, needed);
- // 填充平面指针与步幅
- av_image_fill_arrays(m_data, m_linesize, m_buffer, fmt, pixelW, pixelH, 1);
- }
- ~VideoFrame()
- {
- if (m_buffer)
- free(m_buffer);
- m_buffer = nullptr;
- m_bufSize = 0;
- }
- inline uint8_t* getBufY() const { return m_data[0]; }
- inline uint8_t* getBufU() const { return m_data[1]; }
- inline uint8_t* getBufV() const { return m_data[2]; }
- inline uint8_t* getData(int i) const { return (i >=0 && i < 4) ? m_data[i] : nullptr; }
- inline int getLineSize(int i) const { return (i >=0 && i < 4) ? m_linesize[i] : 0; }
- inline uint32_t getPixelW() const { return m_pixelW; }
- inline uint32_t getPixelH() const { return m_pixelH; }
- inline AVPixelFormat getFormat() const { return m_format; }
- // 设置为纯黑(适用于 YUV 家族,其他格式不保证效果)
- void setToPureBlack()
- {
- if (!m_buffer) return;
- if (m_format == AV_PIX_FMT_YUV420P || m_format == AV_PIX_FMT_YUVJ420P) {
- int sizeY = m_pixelW * m_pixelH;
- memset(m_data[0], 16, sizeY);
- memset(m_data[1], 128, sizeY >> 2);
- memset(m_data[2], 128, sizeY >> 2);
- } else if (m_format == AV_PIX_FMT_YUV422P) {
- int sizeY = m_pixelW * m_pixelH;
- memset(m_data[0], 16, sizeY);
- memset(m_data[1], 128, sizeY >> 1);
- memset(m_data[2], 128, sizeY >> 1);
- } else if (m_format == AV_PIX_FMT_YUV444P) {
- int sizeY = m_pixelW * m_pixelH;
- memset(m_data[0], 16, sizeY);
- memset(m_data[1], 128, sizeY);
- memset(m_data[2], 128, sizeY);
- } else {
- // 其他格式:简单清零
- memset(m_buffer, 0, m_bufSize);
- }
- }
- private:
- void allocateAndCopy(uint8_t* const data[4], const int linesize[4])
- {
- int needed = av_image_get_buffer_size(m_format, m_pixelW, m_pixelH, 1);
- if (needed <= 0) return;
- m_buffer = (uint8_t*)malloc(needed);
- if (!m_buffer) return;
- m_bufSize = needed;
- // 将给定 data/linesize 拷贝到连续缓冲区
- av_image_copy_to_buffer(m_buffer,
- needed,
- (const uint8_t* const*)data,
- linesize,
- m_format,
- m_pixelW,
- m_pixelH,
- 1);
- // 填充平面指针与步幅
- av_image_fill_arrays(m_data, m_linesize, m_buffer, m_format, m_pixelW, m_pixelH, 1);
- }
- uint8_t* m_buffer;
- int m_bufSize;
- AVPixelFormat m_format;
- uint32_t m_pixelW;
- uint32_t m_pixelH;
- uint8_t* m_data[4] = {nullptr, nullptr, nullptr, nullptr};
- int m_linesize[4] = {0, 0, 0, 0};
- };
- #endif // VFRAME_H
|