vframe.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #ifndef VFRAME_H
  2. #define VFRAME_H
  3. #include <QObject>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "ffmpeg_compat.h"
  7. class VideoFrame
  8. {
  9. public:
  10. // 从各平面数据+步幅构建,内部拷贝成为自有连续缓冲区
  11. VideoFrame(AVPixelFormat fmt,
  12. uint32_t pixelW,
  13. uint32_t pixelH,
  14. uint8_t* const data[4],
  15. const int linesize[4])
  16. : m_buffer(nullptr)
  17. , m_bufSize(0)
  18. , m_format(fmt)
  19. , m_pixelW(pixelW)
  20. , m_pixelH(pixelH)
  21. {
  22. allocateAndCopy(data, linesize);
  23. }
  24. // 从连续内存基址构建(假定按 align=1 的 FFmpeg 平面布局),用于快速拷贝
  25. VideoFrame(AVPixelFormat fmt, uint32_t pixelW, uint32_t pixelH, const uint8_t* base)
  26. : m_buffer(nullptr)
  27. , m_bufSize(0)
  28. , m_format(fmt)
  29. , m_pixelW(pixelW)
  30. , m_pixelH(pixelH)
  31. {
  32. int needed = av_image_get_buffer_size(fmt, pixelW, pixelH, 1);
  33. if (needed <= 0) return;
  34. m_buffer = (uint8_t*)malloc(needed);
  35. if (!m_buffer) return;
  36. m_bufSize = needed;
  37. memcpy(m_buffer, base, needed);
  38. // 填充平面指针与步幅
  39. av_image_fill_arrays(m_data, m_linesize, m_buffer, fmt, pixelW, pixelH, 1);
  40. }
  41. ~VideoFrame()
  42. {
  43. if (m_buffer)
  44. free(m_buffer);
  45. m_buffer = nullptr;
  46. m_bufSize = 0;
  47. }
  48. inline uint8_t* getBufY() const { return m_data[0]; }
  49. inline uint8_t* getBufU() const { return m_data[1]; }
  50. inline uint8_t* getBufV() const { return m_data[2]; }
  51. inline uint8_t* getData(int i) const { return (i >=0 && i < 4) ? m_data[i] : nullptr; }
  52. inline int getLineSize(int i) const { return (i >=0 && i < 4) ? m_linesize[i] : 0; }
  53. inline uint32_t getPixelW() const { return m_pixelW; }
  54. inline uint32_t getPixelH() const { return m_pixelH; }
  55. inline AVPixelFormat getFormat() const { return m_format; }
  56. // 设置为纯黑(适用于 YUV 家族,其他格式不保证效果)
  57. void setToPureBlack()
  58. {
  59. if (!m_buffer) return;
  60. if (m_format == AV_PIX_FMT_YUV420P || m_format == AV_PIX_FMT_YUVJ420P) {
  61. int sizeY = m_pixelW * m_pixelH;
  62. memset(m_data[0], 16, sizeY);
  63. memset(m_data[1], 128, sizeY >> 2);
  64. memset(m_data[2], 128, sizeY >> 2);
  65. } else if (m_format == AV_PIX_FMT_YUV422P) {
  66. int sizeY = m_pixelW * m_pixelH;
  67. memset(m_data[0], 16, sizeY);
  68. memset(m_data[1], 128, sizeY >> 1);
  69. memset(m_data[2], 128, sizeY >> 1);
  70. } else if (m_format == AV_PIX_FMT_YUV444P) {
  71. int sizeY = m_pixelW * m_pixelH;
  72. memset(m_data[0], 16, sizeY);
  73. memset(m_data[1], 128, sizeY);
  74. memset(m_data[2], 128, sizeY);
  75. } else {
  76. // 其他格式:简单清零
  77. memset(m_buffer, 0, m_bufSize);
  78. }
  79. }
  80. private:
  81. void allocateAndCopy(uint8_t* const data[4], const int linesize[4])
  82. {
  83. int needed = av_image_get_buffer_size(m_format, m_pixelW, m_pixelH, 1);
  84. if (needed <= 0) return;
  85. m_buffer = (uint8_t*)malloc(needed);
  86. if (!m_buffer) return;
  87. m_bufSize = needed;
  88. // 将给定 data/linesize 拷贝到连续缓冲区
  89. av_image_copy_to_buffer(m_buffer,
  90. needed,
  91. (const uint8_t* const*)data,
  92. linesize,
  93. m_format,
  94. m_pixelW,
  95. m_pixelH,
  96. 1);
  97. // 填充平面指针与步幅
  98. av_image_fill_arrays(m_data, m_linesize, m_buffer, m_format, m_pixelW, m_pixelH, 1);
  99. }
  100. uint8_t* m_buffer;
  101. int m_bufSize;
  102. AVPixelFormat m_format;
  103. uint32_t m_pixelW;
  104. uint32_t m_pixelH;
  105. uint8_t* m_data[4] = {nullptr, nullptr, nullptr, nullptr};
  106. int m_linesize[4] = {0, 0, 0, 0};
  107. };
  108. #endif // VFRAME_H