#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
