You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

FfmpegDecodeNew.cpp 7.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "FfmpegDecodeNew.h"
  2. FfmpegDecodeNew::FfmpegDecodeNew(QObject* parent)
  3. : QThread(parent)
  4. , m_bNeedWork(false)
  5. , m_pConstBuffer(nullptr)
  6. , m_pAVPacket(nullptr)
  7. , m_pAVCodec(nullptr)
  8. , m_pAVCodecParserContext(nullptr)
  9. , m_pAVCodecContext(nullptr)
  10. , m_pAVFrameSrc(nullptr)
  11. , m_pAVFrameDes(nullptr)
  12. , m_pSwsContext(nullptr)
  13. , m_bSwsContext(false)
  14. , m_bImageUpdated(false)
  15. , m_iWidth(0) // 图像宽度
  16. , m_iHeight(0) // 图像高度
  17. {
  18. m_pConstBuffer = new ConstBuffer(VideoBufferLength, false, false, VideoPacketLength);
  19. }
  20. FfmpegDecodeNew::~FfmpegDecodeNew()
  21. {
  22. if (m_pConstBuffer) {
  23. delete m_pConstBuffer;
  24. m_pConstBuffer = nullptr;
  25. }
  26. }
  27. void FfmpegDecodeNew::setParam(unsigned short format, int width, int height)
  28. {
  29. m_usFormat = format;
  30. m_iWidth = width;
  31. m_iHeight = height;
  32. switch (m_usFormat) {
  33. case 1: // 444P
  34. m_AVPixelFormat = AV_PIX_FMT_YUV444P;
  35. break;
  36. case 2: // 422P
  37. m_AVPixelFormat = AV_PIX_FMT_YUV422P;
  38. break;
  39. case 3: // 420P
  40. m_AVPixelFormat = AV_PIX_FMT_YUV420P;
  41. break;
  42. case 4: // NV12
  43. m_AVPixelFormat = AV_PIX_FMT_NV12;
  44. break;
  45. case 5: // RGB24
  46. m_AVPixelFormat = AV_PIX_FMT_RGB24;
  47. break;
  48. default:
  49. break;
  50. }
  51. }
  52. void FfmpegDecodeNew::init()
  53. {
  54. // (1)注册所有编解码器(codecs)、解析器(parsers)以及码流过滤器(bitstream filters)
  55. avcodec_register_all();
  56. // (2)申请分配压缩数据包空间
  57. m_pAVPacket = av_packet_alloc();
  58. if (!m_pAVPacket) { // 申请分配压缩数据包空间失败
  59. return;
  60. }
  61. // (3)查找H264压缩格式视频解码器
  62. m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
  63. if (!m_pAVCodec) { // 未找到编解码器
  64. return;
  65. }
  66. // (4)查找解析器
  67. m_pAVCodecParserContext = av_parser_init(m_pAVCodec->id);
  68. if (!m_pAVCodecParserContext) { // 未找到解析器
  69. return;
  70. }
  71. // (5)分配视频编解码器上下文
  72. m_pAVCodecContext = avcodec_alloc_context3(m_pAVCodec);
  73. if (!m_pAVCodecContext) { // 无法分配视频编解码器上下文
  74. return;
  75. }
  76. // (6)打开解码器
  77. if (avcodec_open2(m_pAVCodecContext, m_pAVCodec, NULL) < 0) {
  78. return;
  79. }
  80. // (7)申请视频帧
  81. m_pAVFrameSrc = av_frame_alloc();
  82. if (!m_pAVFrameSrc) { // 申请视频帧存储空间失败
  83. return;
  84. }
  85. av_image_alloc(m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, m_iWidth, m_iHeight,
  86. m_AVPixelFormat, 1);
  87. // (11)申请转换后视频帧
  88. m_pAVFrameDes = av_frame_alloc();
  89. if (!m_pAVFrameDes) {
  90. return;
  91. }
  92. av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, m_iWidth, m_iHeight,
  93. AV_PIX_FMT_RGB24, 1);
  94. /*
  95. int numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, m_iWidth, m_iHeight);
  96. uint8_t* pBuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
  97. m_pAVFrameDes = av_frame_alloc();
  98. m_pAVFrameDes->data[0] = pBuffer;
  99. avpicture_fill((AVPicture*)m_pAVFrameDes, pBuffer, AV_PIX_FMT_RGB24, m_iWidth, m_iHeight);
  100. */
  101. // (12)初始化图像格式转换
  102. /*m_pSwsContext = sws_getContext(m_iWidth, m_iHeight, m_AVPixelFormat,
  103. m_iWidth, m_iHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);*/
  104. m_pSwsContext = sws_getContext(m_iWidth, m_iHeight, (AVPixelFormat)m_AVPixelFormat, m_iWidth,
  105. m_iHeight, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  106. }
  107. void FfmpegDecodeNew::run()
  108. {
  109. m_bNeedWork = true;
  110. unsigned short usRecvSize = 0;
  111. unsigned char* pVideoBuffer = new unsigned char[VideoPacketLength];
  112. int ret = 0;
  113. while (m_bNeedWork) {
  114. usRecvSize = m_pConstBuffer->read(pVideoBuffer, VideoPacketLength);
  115. if (usRecvSize <= 0) {
  116. continue;
  117. }
  118. unsigned char* pBuffer = pVideoBuffer;
  119. while (0 < usRecvSize) {
  120. // (8)获取AVPacket压缩数据
  121. ret = av_parser_parse2(m_pAVCodecParserContext, m_pAVCodecContext, &(m_pAVPacket->data),
  122. &(m_pAVPacket->size), pBuffer, usRecvSize, AV_NOPTS_VALUE,
  123. AV_NOPTS_VALUE, 0);
  124. if (ret < 0) {
  125. return;
  126. }
  127. pBuffer += ret;
  128. usRecvSize -= ret;
  129. if (m_pAVPacket->size) { // 说明获取到AVPacket压缩数据
  130. decode(m_pAVCodecContext, m_pAVFrameSrc, m_pAVPacket);
  131. }
  132. }
  133. }
  134. }
  135. void FfmpegDecodeNew::decode(AVCodecContext* pCodecContext, AVFrame* pFrame, AVPacket* pPacket)
  136. {
  137. // (9)发送AVPacket数据到Ffmepg,放到解码队列中
  138. int ret = avcodec_send_packet(pCodecContext, pPacket);
  139. if (ret < 0) {
  140. return;
  141. }
  142. while (0 <= ret) {
  143. // (10)从解码队列中取出1个AVFrame数据
  144. ret = avcodec_receive_frame(pCodecContext, pFrame);
  145. if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
  146. return;
  147. } else if (ret < 0) {
  148. return;
  149. }
  150. /*
  151. //验证一下是否可以根据pFrame对m_pAVFrameDes操作av_image_alloc和sws_getContext
  152. if (m_bSwsContext == false) {
  153. av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, pFrame->width,
  154. pFrame->height, AV_PIX_FMT_RGB24, 1);
  155. //(12)初始化图像格式转换
  156. m_pSwsContext = sws_getContext(pFrame->width, pFrame->height,
  157. (AVPixelFormat)pFrame->format, pFrame->width, pFrame->height, AV_PIX_FMT_RGB24,
  158. SWS_FAST_BILINEAR, NULL, NULL, NULL); m_iWidth = pFrame->width; //图像宽度 m_iHeight =
  159. pFrame->height; //图像高度 m_bSwsContext = true;
  160. }
  161. if (m_bSwsContext == true) {
  162. // (13) 进行图像格式转换
  163. sws_scale(m_pSwsContext, m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, 0,
  164. m_pAVFrameSrc->height, m_pAVFrameDes->data, m_pAVFrameDes->linesize);
  165. //(14)对转换后的数据进行处理
  166. m_bImageUpdated = true;
  167. m_image = QImage((uchar*)m_pAVFrameDes->data[0],
  168. m_iWidth,m_iHeight,QImage::Format_RGB888);
  169. }
  170. */
  171. // (13) 进行图像格式转换
  172. sws_scale(m_pSwsContext, pFrame->data, pFrame->linesize, 0, pCodecContext->height,
  173. m_pAVFrameDes->data, m_pAVFrameDes->linesize);
  174. // (14)对转换后的数据进行处理
  175. QMutexLocker locker(&m_mutex);
  176. m_bImageUpdated = true;
  177. m_image =
  178. QImage((uchar*)m_pAVFrameDes->data[0], m_iWidth, m_iHeight, QImage::Format_RGB888);
  179. }
  180. }
  181. bool FfmpegDecodeNew::getImage(QImage& image)
  182. {
  183. QMutexLocker locker(&m_mutex);
  184. if (m_bImageUpdated) {
  185. image = m_image;
  186. m_bImageUpdated = false;
  187. return true;
  188. }
  189. return false;
  190. }