123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- #include "Transcode.h"
- #include "LHQLogAPI.h"
- #if(USING_FFMPEG == true)
- extern "C"
- {
- #include "libavcodec/avcodec.h"
- #include "libswscale/swscale.h"
- #include "libavutil/pixfmt.h"
- #include "libavutil/imgutils.h"
- }
- #endif // USING_FFMPEG
- TransCode::TransCode()
- {
- }
- TransCode::~TransCode()
- {
- #if(USING_FFMPEG == true)
- if(m_swsCtx != nullptr)
- {
- sws_freeContext(m_swsCtx);
- m_swsCtx = nullptr;
- }
- #endif // USING_FFMPEG
- }
- /* 使用ffmpeg将yv12转换成RGB24 */
- // bool YV12ToRGB24_FFmpeg(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
- // {
- // if (width < 1 || height < 1 || pYV12Data == NULL || pRGB24Data == NULL)
- // return false;
- // //int srcNumBytes,dstNumBytes;
- // //uint8_t *pSrc,*pDst;
- // AVPicture pFrameYUV, pFrameBGR;
-
- // //pFrameYUV = avpicture_alloc();
- // //srcNumBytes = avpicture_get_size(PIX_FMT_YUV420P,width,height);
- // //pSrc = (uint8_t *)malloc(sizeof(uint8_t) * srcNumBytes);
- // avpicture_fill(&pFrameYUV, pYV12Data, AV_PIX_FMT_YUV420P, width, height);
- // //U,V互换
- // uint8_t * ptmp=pFrameYUV.data[1];
- // pFrameYUV.data[1]=pFrameYUV.data[2];
- // pFrameYUV.data [2]=ptmp;
- // //pFrameBGR = avcodec_alloc_frame();
- // //dstNumBytes = avpicture_get_size(PIX_FMT_BGR24,width,height);
- // //pDst = (uint8_t *)malloc(sizeof(uint8_t) * dstNumBytes);
- // avpicture_fill(&pFrameBGR, pRGB24Data, AV_PIX_FMT_BGR24, width,height);
- // struct SwsContext* imgCtx = NULL;
- // imgCtx = sws_getContext(width,height, AV_PIX_FMT_YUV420P, width, height, AV_PIX_FMT_BGR24,SWS_BILINEAR, 0, 0, 0);
- // if (imgCtx != NULL){
- // sws_scale(imgCtx,pFrameYUV.data,pFrameYUV.linesize,0,height,pFrameBGR.data,pFrameBGR.linesize);
- // if(imgCtx){
- // sws_freeContext(imgCtx);
- // imgCtx = NULL;
- // }
- // return true;
- // }
- // else{
- // sws_freeContext(imgCtx);
- // imgCtx = NULL;
- // return false;
- // }
- // }
- #if(USING_FFMPEG == true)
- bool TransCode::YV12ToRGB24_FFmpeg(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
- {
- int ret = 0;
- /* 创建AVFrame */
- AVFrame* pFrameYV12 = av_frame_alloc();
- AVFrame* pFrameBGR = av_frame_alloc();
- /* 将pFrameYV12与pYV12Data相关联 */
- ret = av_image_fill_arrays(pFrameYV12->data, pFrameYV12->linesize, pYV12Data, AV_PIX_FMT_YUV420P, width, height, 1);
- if(ret < 0)
- {
- av_frame_free(&pFrameYV12);
- av_frame_free(&pFrameBGR);
- return false;
- }
- /* UV互换,海康的UV是反的 */
- uint8_t* pTmp = pFrameYV12->data[1];
- pFrameYV12->data[1] = pFrameYV12->data[2];
- pFrameYV12->data[2] = pTmp;
- /* 将pFrameBGR和数组pRGB24Data关联起来 */
- // ret = av_image_fill_arrays(pFrameBGR->data, pFrameBGR->linesize, pRGB24Data, AV_PIX_FMT_BGR24, width, height, 1);
- ret = av_image_fill_arrays(pFrameBGR->data, pFrameBGR->linesize, pRGB24Data, AV_PIX_FMT_RGB24, width, height, 1);
- if(ret < 0)
- {
- av_frame_free(&pFrameYV12);
- av_frame_free(&pFrameBGR);
- return false;
- }
- /* 获取转码上下文 */
- if(m_swsCtx == nullptr)
- {
- m_swsCtx = sws_getCachedContext(m_swsCtx,
- width, height, /* 原图像大小和格式 */
- AV_PIX_FMT_YUV420P, /* 输入图像的像素格式 */
- width, height, /* 目标图像的大小 */
- AV_PIX_FMT_RGB24, /* 目标图像的格式 */
- SWS_BILINEAR, /* 图像缩放算法,双线性 */
- nullptr, /* 输入图像的滤波器信息,不需要传NULL */
- nullptr, /* 输出图像的滤波器信息,不需要传NULL */
- nullptr); /* 特定缩放算法需要的参数,不需要传NULL */
- }
- /* 转换图像 */
- bool result = false;
- if(m_swsCtx != nullptr)
- {
- sws_scale(m_swsCtx, pFrameYV12->data, pFrameYV12->linesize, 0, height, pFrameBGR->data, pFrameBGR->linesize);
- result = true;
- }else {
- LH_WRITE_ERROR(QString("获取转码上下文失败"));
- result = false;
- }
- /* 释放资源 */
- av_frame_free(&pFrameYV12);
- av_frame_free(&pFrameBGR);
- return result;
- }
- #else
- bool TransCode::YV12ToRGB24_FFmpeg(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
- {
- return false;
- }
- #endif // USING_FFMPEG
- /* YV12转RGB888 */
- void TransCode::YV12ToRGB888(unsigned char *pYV12Data, unsigned char *pRGB24Data, int width, int height)
- {
- int ySize = width * height;
- int uvSize = ySize / 4;
- const uint8_t* yData = pYV12Data;
- const uint8_t* vData = pYV12Data + ySize;
- const uint8_t* uData = pYV12Data + ySize + uvSize;
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- int yIndex = y * width + x;
- int uvIndex = (y / 2) * (width / 2) + (x / 2);
- uint8_t Y = yData[yIndex];
- uint8_t U = uData[uvIndex];
- uint8_t V = vData[uvIndex];
- // YUV 转 RGB
- int R = Y + 1.403 * (V - 128);
- int G = Y - 0.344 * (U - 128) - 0.714 * (V - 128);
- int B = Y + 1.770 * (U - 128);
- // 限制范围 [0, 255]
- R = std::min(std::max(R, 0), 255);
- G = std::min(std::max(G, 0), 255);
- B = std::min(std::max(B, 0), 255);
- // 存储 RGB 数据
- int rgbIndex = yIndex * 3;
- pRGB24Data[rgbIndex] = static_cast<uint8_t>(R);
- pRGB24Data[rgbIndex + 1] = static_cast<uint8_t>(G);
- pRGB24Data[rgbIndex + 2] = static_cast<uint8_t>(B);
- }
- }
- }
- /* RGB888转QImage */
- void TransCode::YV12ToQImage(unsigned char *pYV12Data, Image_QImage& image, int width, int height)
- {
- unsigned char* rgbData = new unsigned char [width * height * 3];
- YV12ToRGB888(pYV12Data, rgbData, width, height);
- if(rgbData != nullptr)
- // if(YV12ToRGB24_FFmpeg(pYV12Data, rgbData, width, height))
- {
- image.image = QImage(rgbData, width, height, QImage::Format_RGB888);
- image.width = width;
- image.height = height;
- }else {
- LH_WRITE_ERROR("YV12ToRGB24_FFmpeg failed!");
- }
-
- /* 释放资源 */
- delete [] rgbData;
- }
- /* YV12转YUV420 */
- void TransCode::YV12ToYUV420(unsigned char *pYV12Data, Image_YUV420& yuvData, int width, int height)
- {
- int y_size = width * height;
- int uv_size = y_size / 4;
- // 分配 YUV 数据的空间
- yuvData.yData.resize(y_size);
- yuvData.uData.resize(uv_size);
- yuvData.vData.resize(uv_size);
- yuvData.width = width;
- yuvData.height = height;
- // 提取 Y、V、U 分量,交换uv分量,海康的uv是反的
- const uint8_t* y = pYV12Data;
- const uint8_t* v = pYV12Data + y_size;
- const uint8_t* u = pYV12Data + y_size + uv_size;
- // 复制 Y 分量
- std::memcpy(yuvData.yData.data(), y, y_size);
- // 复制 U 分量
- std::memcpy(yuvData.uData.data(), u, uv_size);
- // 复制 V 分量
- std::memcpy(yuvData.vData.data(), v, uv_size);
- }
|