#ifndef VFRAME_H #define VFRAME_H #include #include #include #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