CVideoDecoder.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "CVideoDecoder.h"
  2. #include <Windows.h>
  3. extern "C"
  4. {
  5. #include "libavcodec/avcodec.h"
  6. #include "libavformat/avformat.h"
  7. #include "libswscale/swscale.h"
  8. #include "libavdevice/avdevice.h"
  9. #include "libavutil/opt.h"
  10. #include "libavfilter/avfilter.h"
  11. #include "libavfilter/buffersrc.h"
  12. #include "libavfilter/buffersink.h"
  13. #include "libavutil/imgutils.h"
  14. #include "libavutil/frame.h"
  15. };
  16. #include "CVideoDataManager.h"
  17. #include "../Include/libyuv.h"
  18. #include "FusionAndTailor.cuh"
  19. CVideoDecoder::CVideoDecoder(AVCodecContext* pDecoder, bool bHard, CVideoDataManager* pDataManager)
  20. {
  21. m_pDecoder = pDecoder;
  22. m_pDataManager = pDataManager;
  23. m_bHard = bHard;
  24. m_pDataManager->SetDecodeDataSize(m_pDecoder->width* m_pDecoder->height*3/2);
  25. _beginthreadex(nullptr, 0, &CVideoDecoder::DecodeThread, this, 0, 0);
  26. CUstream Cur = ((CUstream)pCuStream);
  27. cudaError Err = cudaStreamCreate(&(Cur));
  28. pCuStream = Cur;
  29. }
  30. CVideoDecoder::~CVideoDecoder()
  31. {
  32. if (m_pDecoder != nullptr)
  33. {
  34. avcodec_close(m_pDecoder);
  35. m_pDecoder = nullptr;
  36. }
  37. }
  38. unsigned __stdcall CVideoDecoder::DecodeThread(void* param)
  39. {
  40. CVideoDecoder* pThis = (CVideoDecoder*)param;
  41. pThis->DecodeProcessor();
  42. return 0;
  43. }
  44. void CVideoDecoder::DecodeProcessor()
  45. {
  46. while (true)
  47. {
  48. //if (m_pDataManager->GetSyncDataSize() > 0)
  49. {
  50. CPacketInfo* pPack = nullptr;
  51. if (m_pDataManager->GetSyncData(pPack))
  52. {
  53. uint8_t* pData = nullptr;
  54. DecodePacket(pPack->m_pPkt, pData);
  55. //DecodePacketGpu(pPack->m_pPkt, pData);
  56. m_pDataManager->AddDecoderData(pData, pPack->m_dPtzAngle);
  57. m_pDataManager->ReleaseSyncData(pPack);
  58. }
  59. }
  60. Sleep(5);
  61. }
  62. }
  63. bool CVideoDecoder::DecodePacket(AVPacket* pkt, unsigned char* & pData)
  64. {
  65. int nRet = 0;
  66. AVFrame* tmp_frame = nullptr;
  67. avcodec_send_packet(m_pDecoder, pkt);
  68. AVFrame* pFrame = av_frame_alloc();
  69. nRet = avcodec_receive_frame(m_pDecoder, pFrame);
  70. pData = new unsigned char[pFrame->linesize[0] * pFrame->height *3];
  71. if (m_bHard)
  72. {
  73. // 如果采用的硬件加速剂,则调用avcodec_receive_frame()函数后,解码后的数据还在GPU中,所以需要通过此函数
  74. // 将GPU中的数据转移到CPU中来
  75. tmp_frame = av_frame_alloc();
  76. if (av_hwframe_transfer_data(tmp_frame, pFrame, 0) < 0)
  77. {
  78. return false;
  79. }
  80. if (pFrame != nullptr)
  81. {
  82. av_frame_free(&pFrame);
  83. pFrame = nullptr;
  84. }
  85. pFrame = tmp_frame;
  86. //libyuv::NV12ToI420(
  87. // pFrame->data[0], pFrame->linesize[0],
  88. // pFrame->data[1], pFrame->linesize[1],
  89. // pData, pFrame->width,
  90. // pData + pFrame->width * pFrame->height, pFrame->width / 2,
  91. // pData + pFrame->width * pFrame->height * 5 / 4, pFrame->width / 2,
  92. // pFrame->width, pFrame->height
  93. //);
  94. libyuv::NV12ToRGB24(
  95. pFrame->data[0], pFrame->linesize[0],
  96. pFrame->data[1], pFrame->linesize[1],
  97. pData, pFrame->width * 3,
  98. pFrame->width, pFrame->height
  99. );
  100. }
  101. else
  102. {
  103. int dst_stride_y2 = pFrame->width;
  104. int dst_stride_u2 = dst_stride_y2 / 2;
  105. int dst_stride_v2 = dst_stride_y2 / 2;
  106. libyuv::I420Copy(pFrame->data[0], pFrame->linesize[0], pFrame->data[1], pFrame->linesize[1], pFrame->data[2], pFrame->linesize[2],
  107. pData, pFrame->width, pData + pFrame->width * pFrame->height, pFrame->width/2, pData + pFrame->width * pFrame->height * 5 / 4, pFrame->width / 2,
  108. pFrame->width, pFrame->height);
  109. }
  110. //cv::Mat mat(pFrame->height * 3 / 2, pFrame->width, CV_8UC1, pData);
  111. av_frame_free(&pFrame);
  112. pFrame = nullptr;
  113. return true;
  114. }
  115. //注意该函数返回的指针指向的是显存数据,
  116. bool CVideoDecoder::DecodePacketGpu(AVPacket* pkt, unsigned char*& pData)
  117. {
  118. int nRet = 0;
  119. AVFrame* tmp_frame = nullptr;
  120. avcodec_send_packet(m_pDecoder, pkt);
  121. AVFrame* pFrame = av_frame_alloc();
  122. nRet = avcodec_receive_frame(m_pDecoder, pFrame);
  123. pFrame->format = AV_PIX_FMT_NV12;
  124. CUstream CurStream = (CUstream)pCuStream;
  125. if (m_pI420 == nullptr)
  126. {
  127. cudaMalloc(&m_pI420, pFrame->width * pFrame->height * 3 / 2);
  128. YUVTailorAndBlender::setColorSpace2(0);
  129. }
  130. YUVTailorAndBlender::TurnCUDAFormatToI420(pFrame->data[0], pFrame->data[1],
  131. pFrame->linesize[0], pFrame->linesize[1], m_pI420, pFrame->width, pFrame->height, &CurStream);
  132. cudaError err = cudaDeviceSynchronize();
  133. if (pData != nullptr)
  134. cudaFree(pData);
  135. cudaMalloc((void**)&pData, pFrame->width * pFrame->height * 3 / 2);
  136. cudaMemcpy(pData,m_pI420 , pFrame->width * pFrame->height * 3 / 2, cudaMemcpyDeviceToDevice);
  137. //下载
  138. //cudaMemcpy(pData, m_pI420, pFrame->width * pFrame->height * 3/2, cudaMemcpyDeviceToHost);
  139. //FILE* file = fopen("111.yuv", "wb"); //已只读方式打开
  140. //fwrite(pData, 1, pFrame->height * pFrame->width, file); //写入操作
  141. //fwrite(pData + pFrame->height* pFrame->width, 1, pFrame->height * pFrame->width/4, file); //写入操作
  142. //fwrite(pData + pFrame->height * pFrame->width*5/4, 1, pFrame->height * pFrame->width/4, file); //写入操作
  143. //fclose(file);
  144. av_frame_free(&pFrame);
  145. return false;
  146. }