Transcode.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "Transcode.h"
  2. #include "LHQLogAPI.h"
  3. extern "C"
  4. {
  5. #include "libavcodec/avcodec.h"
  6. #include "libswscale/swscale.h"
  7. #include "libavutil/pixfmt.h"
  8. #include "libavutil/imgutils.h"
  9. }
  10. TransCode::TransCode()
  11. {
  12. }
  13. TransCode::~TransCode()
  14. {
  15. if(m_swsCtx != nullptr)
  16. {
  17. sws_freeContext(m_swsCtx);
  18. m_swsCtx = nullptr;
  19. }
  20. }
  21. /* 使用ffmpeg将yv12转换成RGB24 */
  22. // bool YV12ToRGB24_FFmpeg(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
  23. // {
  24. // if (width < 1 || height < 1 || pYV12Data == NULL || pRGB24Data == NULL)
  25. // return false;
  26. // //int srcNumBytes,dstNumBytes;
  27. // //uint8_t *pSrc,*pDst;
  28. // AVPicture pFrameYUV, pFrameBGR;
  29. // //pFrameYUV = avpicture_alloc();
  30. // //srcNumBytes = avpicture_get_size(PIX_FMT_YUV420P,width,height);
  31. // //pSrc = (uint8_t *)malloc(sizeof(uint8_t) * srcNumBytes);
  32. // avpicture_fill(&pFrameYUV, pYV12Data, AV_PIX_FMT_YUV420P, width, height);
  33. // //U,V互换
  34. // uint8_t * ptmp=pFrameYUV.data[1];
  35. // pFrameYUV.data[1]=pFrameYUV.data[2];
  36. // pFrameYUV.data [2]=ptmp;
  37. // //pFrameBGR = avcodec_alloc_frame();
  38. // //dstNumBytes = avpicture_get_size(PIX_FMT_BGR24,width,height);
  39. // //pDst = (uint8_t *)malloc(sizeof(uint8_t) * dstNumBytes);
  40. // avpicture_fill(&pFrameBGR, pRGB24Data, AV_PIX_FMT_BGR24, width,height);
  41. // struct SwsContext* imgCtx = NULL;
  42. // imgCtx = sws_getContext(width,height, AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_BGR24,SWS_BILINEAR, 0, 0, 0);
  43. // if (imgCtx != NULL){
  44. // sws_scale(imgCtx,pFrameYUV.data,pFrameYUV.linesize,0,height,pFrameBGR.data,pFrameBGR.linesize);
  45. // if(imgCtx){
  46. // sws_freeContext(imgCtx);
  47. // imgCtx = NULL;
  48. // }
  49. // return true;
  50. // }
  51. // else{
  52. // sws_freeContext(imgCtx);
  53. // imgCtx = NULL;
  54. // return false;
  55. // }
  56. // }
  57. bool TransCode::YV12ToRGB24_FFmpeg(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
  58. {
  59. int ret = 0;
  60. /* 创建AVFrame */
  61. AVFrame* pFrameYV12 = av_frame_alloc();
  62. AVFrame* pFrameBGR = av_frame_alloc();
  63. /* 将pFrameYV12与pYV12Data相关联 */
  64. ret = av_image_fill_arrays(pFrameYV12->data, pFrameYV12->linesize, pYV12Data, AV_PIX_FMT_YUV420P, width, height, 1);
  65. if(ret < 0)
  66. {
  67. av_frame_free(&pFrameYV12);
  68. av_frame_free(&pFrameBGR);
  69. return false;
  70. }
  71. /* UV互换,海康的UV是反的 */
  72. uint8_t* pTmp = pFrameYV12->data[1];
  73. pFrameYV12->data[1] = pFrameYV12->data[2];
  74. pFrameYV12->data[2] = pTmp;
  75. /* 将pFrameBGR和数组pRGB24Data关联起来 */
  76. // ret = av_image_fill_arrays(pFrameBGR->data, pFrameBGR->linesize, pRGB24Data, AV_PIX_FMT_BGR24, width, height, 1);
  77. ret = av_image_fill_arrays(pFrameBGR->data, pFrameBGR->linesize, pRGB24Data, AV_PIX_FMT_RGB24, width, height, 1);
  78. if(ret < 0)
  79. {
  80. av_frame_free(&pFrameYV12);
  81. av_frame_free(&pFrameBGR);
  82. return false;
  83. }
  84. /* 获取转码上下文 */
  85. if(m_swsCtx == nullptr)
  86. {
  87. m_swsCtx = sws_getCachedContext(m_swsCtx,
  88. width, height, /* 原图像大小和格式 */
  89. AV_PIX_FMT_YUV420P, /* 输入图像的像素格式 */
  90. width, height, /* 目标图像的大小 */
  91. AV_PIX_FMT_RGB24, /* 目标图像的格式 */
  92. SWS_BILINEAR, /* 图像缩放算法,双线性 */
  93. nullptr, /* 输入图像的滤波器信息,不需要传NULL */
  94. nullptr, /* 输出图像的滤波器信息,不需要传NULL */
  95. nullptr); /* 特定缩放算法需要的参数,不需要传NULL */
  96. }
  97. /* 转换图像 */
  98. bool result = false;
  99. if(m_swsCtx != nullptr)
  100. {
  101. sws_scale(m_swsCtx, pFrameYV12->data, pFrameYV12->linesize, 0, height, pFrameBGR->data, pFrameBGR->linesize);
  102. result = true;
  103. }else {
  104. LH_WRITE_ERROR(QString("获取转码上下文失败"));
  105. result = false;
  106. }
  107. /* 释放资源 */
  108. av_frame_free(&pFrameYV12);
  109. av_frame_free(&pFrameBGR);
  110. return result;
  111. }
  112. /* YV12转RGB888 */
  113. void TransCode::YV12ToRGB888(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
  114. {
  115. int ySize = width * height;
  116. int uvSize = ySize / 4;
  117. const uint8_t* yData = pYV12Data;
  118. const uint8_t* vData = pYV12Data + ySize;
  119. const uint8_t* uData = pYV12Data + ySize + uvSize;
  120. for (int y = 0; y < height; y++) {
  121. for (int x = 0; x < width; x++) {
  122. int yIndex = y * width + x;
  123. int uvIndex = (y / 2) * (width / 2) + (x / 2);
  124. uint8_t Y = yData[yIndex];
  125. uint8_t U = uData[uvIndex];
  126. uint8_t V = vData[uvIndex];
  127. // YUV 转 RGB
  128. int R = Y + 1.403 * (V - 128);
  129. int G = Y - 0.344 * (U - 128) - 0.714 * (V - 128);
  130. int B = Y + 1.770 * (U - 128);
  131. // 限制范围 [0, 255]
  132. R = std::min(std::max(R, 0), 255);
  133. G = std::min(std::max(G, 0), 255);
  134. B = std::min(std::max(B, 0), 255);
  135. // 存储 RGB 数据
  136. int rgbIndex = yIndex * 3;
  137. pRGB24Data[rgbIndex] = static_cast<uint8_t>(R);
  138. pRGB24Data[rgbIndex + 1] = static_cast<uint8_t>(G);
  139. pRGB24Data[rgbIndex + 2] = static_cast<uint8_t>(B);
  140. }
  141. }
  142. }
  143. /* RGB888转QImage */
  144. void TransCode::YV12ToQImage(unsigned char *pYV12Data, Image_QImage& image, int width, int height)
  145. {
  146. unsigned char* rgbData = new unsigned char [width * height * 3];
  147. // YV12ToRGB888(pYV12Data, rgbData, width, height);
  148. if(YV12ToRGB24_FFmpeg(pYV12Data, rgbData, width, height))
  149. {
  150. image.image = QImage(rgbData, width, height, QImage::Format_RGB888);
  151. image.width = width;
  152. image.height = height;
  153. }else {
  154. LH_WRITE_ERROR("YV12ToRGB24_FFmpeg failed!");
  155. }
  156. /* 释放资源 */
  157. delete [] rgbData;
  158. }
  159. /* YV12转YUV420 */
  160. void TransCode::YV12ToYUV420(unsigned char *pYV12Data, Image_YUV420& yuvData, int width, int height)
  161. {
  162. int y_size = width * height;
  163. int uv_size = y_size / 4;
  164. // 分配 YUV 数据的空间
  165. yuvData.yData.resize(y_size);
  166. yuvData.uData.resize(uv_size);
  167. yuvData.vData.resize(uv_size);
  168. // 提取 Y、V、U 分量,交换uv分量,海康的uv是反的
  169. const uint8_t* y = pYV12Data;
  170. const uint8_t* v = pYV12Data + y_size;
  171. const uint8_t* u = pYV12Data + y_size + uv_size;
  172. // 复制 Y 分量
  173. // std::memcpy(yuvData.yData.data(), y, y_size);
  174. yuvData.yData.append((char*)y, y_size);
  175. // 复制 U 分量
  176. yuvData.uData.append((char*)v, uv_size);
  177. // uint8_t* yuv_u = (uint8_t*)yuvData.uData.data() + y_size;
  178. // for (int i = 0; i < uv_size; ++i) {
  179. // yuv_u[i] = u[i];
  180. // }
  181. // 复制 V 分量
  182. yuvData.vData.append((char*)u, uv_size);
  183. // uint8_t* yuv_v = (uint8_t*)yuvData.vData.data() + y_size + uv_size;
  184. // for (int i = 0; i < uv_size; ++i) {
  185. // yuv_v[i] = v[i];
  186. // }
  187. }