Transcode.cpp 7.3 KB

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