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.

FfmpegDecodeOld.cpp 5.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include "FfmpegDecodeOld.h"
  2. ConstBuffer* FfmpegDecodeOld::m_pConstBuffer =
  3. new ConstBuffer(VideoBufferLength, false, false, VideoPacketLength);
  4. FfmpegDecodeOld::FfmpegDecodeOld(QObject* parent)
  5. : QThread(parent)
  6. , m_bNeedWork(false)
  7. , m_sBufferSize(VideoPacketLength)
  8. , m_pBuffer(nullptr)
  9. , m_pAVIOContext(nullptr)
  10. , m_pAVInputFormat(nullptr)
  11. , m_pAVFormatContext(nullptr)
  12. , m_iId(-1)
  13. , m_pAVPacket(nullptr)
  14. , m_pAVCodec(nullptr)
  15. , m_pAVCodecContext(nullptr)
  16. , m_pAVFrameSrc(nullptr)
  17. , m_pAVFrameDes(nullptr)
  18. , m_pAVCodecParameters(nullptr)
  19. , m_pSwsContext(nullptr)
  20. {}
  21. FfmpegDecodeOld::~FfmpegDecodeOld()
  22. {}
  23. int FfmpegDecodeOld::read_data(void* opaque, uint8_t* buf, int buf_size)
  24. {
  25. FfmpegDecodeOld* pFfmpegDecodeOld = (FfmpegDecodeOld*)opaque;
  26. unsigned short usRecvSize = pFfmpegDecodeOld->getConstBuffer()->read(buf, buf_size);
  27. return usRecvSize;
  28. }
  29. void FfmpegDecodeOld::init()
  30. {
  31. // (1)注册所有编解码器(codecs)、解析器(parsers)以及码流过滤器(bitstream filters)
  32. avcodec_register_all();
  33. // (2)申请内存
  34. m_pBuffer = (uint8_t*)av_malloc(sizeof(uint8_t) * m_sBufferSize);
  35. // (3)申请一个AVIOContext
  36. m_pAVIOContext = avio_alloc_context(m_pBuffer, m_sBufferSize, 0, NULL, read_data, NULL, NULL);
  37. // (4)探测网络流格式
  38. if (av_probe_input_buffer(m_pAVIOContext, &m_pAVInputFormat, "", NULL, 0, 0) < 0) {
  39. return;
  40. }
  41. // (5)申请一个AVFormatContext
  42. m_pAVFormatContext = avformat_alloc_context();
  43. // (6)将申请到的AVIOContext句柄挂载至之前申请的m_pAVFormatContext中
  44. m_pAVFormatContext->pb = m_pAVIOContext;
  45. // (7)打开输入的AVFormatContext
  46. if (avformat_open_input(&m_pAVFormatContext, "", m_pAVInputFormat, NULL) < 0) {
  47. return;
  48. }
  49. // (8)检索流信息
  50. if (avformat_find_stream_info(m_pAVFormatContext, NULL) < 0) {
  51. return;
  52. }
  53. // (9)打印格式信息
  54. av_dump_format(m_pAVFormatContext, 0, "", 0);
  55. // (10)判断是否有视频编码解码器
  56. for (int i = 0; i < m_pAVFormatContext->nb_streams; ++i) {
  57. if (m_pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
  58. m_iId = i;
  59. break;
  60. }
  61. }
  62. if (m_iId == -1) {
  63. avformat_close_input(&m_pAVFormatContext); // 关闭流信息
  64. return;
  65. }
  66. // (11)找到流的解码器
  67. m_pAVCodec = avcodec_find_decoder(m_pAVFormatContext->streams[m_iId]->codecpar->codec_id);
  68. if (!m_pAVCodec) {
  69. return; // 未找到解码器
  70. }
  71. // (12)分配视频编解码器上下文
  72. m_pAVCodecContext = avcodec_alloc_context3(m_pAVCodec);
  73. if (!m_pAVCodecContext) { // 无法分配视频编解码器上下文
  74. return;
  75. }
  76. // (13)将编解码器参数从输入流复制到输出编解码器上下文
  77. m_pAVCodecParameters = m_pAVFormatContext->streams[m_iId]->codecpar;
  78. if (avcodec_parameters_to_context(m_pAVCodecContext,
  79. m_pAVFormatContext->streams[m_iId]->codecpar)
  80. < 0) {
  81. return;
  82. }
  83. // (14)打开解码器
  84. if (avcodec_open2(m_pAVCodecContext, m_pAVCodec, NULL) < 0) {
  85. return;
  86. }
  87. // (15)申请视频帧存储空间
  88. m_pAVFrameSrc = av_frame_alloc();
  89. if (!m_pAVFrameSrc) { // 申请视频帧存储空间失败
  90. return;
  91. }
  92. // (16)申请分配压缩数据包空间
  93. av_init_packet(m_pAVPacket);
  94. if (!m_pAVPacket) { // 申请分配压缩数据包空间失败
  95. return;
  96. }
  97. // (19)初始化图像数据存储空间
  98. m_pAVFrameDes = av_frame_alloc();
  99. if (!m_pAVFrameDes) {
  100. return;
  101. }
  102. av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, m_pAVCodecParameters->width,
  103. m_pAVCodecParameters->height, AV_PIX_FMT_RGB24, 1);
  104. // (20)初始化图像格式转换
  105. m_pSwsContext = sws_getContext(m_pAVCodecParameters->width, m_pAVCodecParameters->height,
  106. (AVPixelFormat)m_pAVCodecParameters->format,
  107. m_pAVCodecParameters->width, m_pAVCodecParameters->height,
  108. AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
  109. }
  110. void FfmpegDecodeOld::run()
  111. {
  112. int get_pict = 0;
  113. int ret = -1;
  114. // (17)获取一个AVPacket数据
  115. while (0 <= av_read_frame(m_pAVFormatContext, m_pAVPacket)) {
  116. if (m_pAVPacket->stream_index == m_iId) {
  117. // (18)对AVPacket数据解码并将数据保存到m_pAVFrame中
  118. if (0 <= avcodec_decode_video2(m_pAVCodecContext, m_pAVFrameSrc, &get_pict,
  119. m_pAVPacket)) {
  120. if (get_pict) {
  121. // (21)进行图像格式转换
  122. sws_scale(m_pSwsContext, m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, 0,
  123. m_pAVFrameSrc->height, m_pAVFrameDes->data, m_pAVFrameDes->linesize);
  124. // (22)对转换后的数据进行处理
  125. }
  126. }
  127. }
  128. }
  129. }