|
- #include "FfmpegDecodeNew.h"
-
- FfmpegDecodeNew::FfmpegDecodeNew(QObject* parent)
- : QThread(parent)
- , m_bNeedWork(false)
- , m_pConstBuffer(nullptr)
- , m_pAVPacket(nullptr)
- , m_pAVCodec(nullptr)
- , m_pAVCodecParserContext(nullptr)
- , m_pAVCodecContext(nullptr)
- , m_pAVFrameSrc(nullptr)
- , m_pAVFrameDes(nullptr)
- , m_pSwsContext(nullptr)
- , m_bSwsContext(false)
- , m_bImageUpdated(false)
- , m_iWidth(0) // 图像宽度
- , m_iHeight(0) // 图像高度
- {
- m_pConstBuffer = new ConstBuffer(VideoBufferLength, false, false, VideoPacketLength);
- }
-
- FfmpegDecodeNew::~FfmpegDecodeNew()
- {
- if (m_pConstBuffer) {
- delete m_pConstBuffer;
- m_pConstBuffer = nullptr;
- }
- }
-
- void FfmpegDecodeNew::setParam(unsigned short format, int width, int height)
- {
- m_usFormat = format;
- m_iWidth = width;
- m_iHeight = height;
- switch (m_usFormat) {
- case 1: // 444P
- m_AVPixelFormat = AV_PIX_FMT_YUV444P;
- break;
- case 2: // 422P
- m_AVPixelFormat = AV_PIX_FMT_YUV422P;
- break;
- case 3: // 420P
- m_AVPixelFormat = AV_PIX_FMT_YUV420P;
- break;
- case 4: // NV12
- m_AVPixelFormat = AV_PIX_FMT_NV12;
- break;
- case 5: // RGB24
- m_AVPixelFormat = AV_PIX_FMT_RGB24;
- break;
- default:
- break;
- }
- }
-
- void FfmpegDecodeNew::init()
- {
- // (1)注册所有编解码器(codecs)、解析器(parsers)以及码流过滤器(bitstream filters)
- avcodec_register_all();
-
- // (2)申请分配压缩数据包空间
- m_pAVPacket = av_packet_alloc();
- if (!m_pAVPacket) { // 申请分配压缩数据包空间失败
- return;
- }
- // (3)查找H264压缩格式视频解码器
- m_pAVCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
- if (!m_pAVCodec) { // 未找到编解码器
- return;
- }
- // (4)查找解析器
- m_pAVCodecParserContext = av_parser_init(m_pAVCodec->id);
- if (!m_pAVCodecParserContext) { // 未找到解析器
- return;
- }
- // (5)分配视频编解码器上下文
- m_pAVCodecContext = avcodec_alloc_context3(m_pAVCodec);
- if (!m_pAVCodecContext) { // 无法分配视频编解码器上下文
- return;
- }
- // (6)打开解码器
- if (avcodec_open2(m_pAVCodecContext, m_pAVCodec, NULL) < 0) {
- return;
- }
- // (7)申请视频帧
- m_pAVFrameSrc = av_frame_alloc();
- if (!m_pAVFrameSrc) { // 申请视频帧存储空间失败
- return;
- }
- av_image_alloc(m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, m_iWidth, m_iHeight,
- m_AVPixelFormat, 1);
- // (11)申请转换后视频帧
- m_pAVFrameDes = av_frame_alloc();
- if (!m_pAVFrameDes) {
- return;
- }
- av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, m_iWidth, m_iHeight,
- AV_PIX_FMT_RGB24, 1);
- /*
- int numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, m_iWidth, m_iHeight);
- uint8_t* pBuffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
- m_pAVFrameDes = av_frame_alloc();
- m_pAVFrameDes->data[0] = pBuffer;
- avpicture_fill((AVPicture*)m_pAVFrameDes, pBuffer, AV_PIX_FMT_RGB24, m_iWidth, m_iHeight);
- */
- // (12)初始化图像格式转换
- /*m_pSwsContext = sws_getContext(m_iWidth, m_iHeight, m_AVPixelFormat,
- m_iWidth, m_iHeight, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);*/
- m_pSwsContext = sws_getContext(m_iWidth, m_iHeight, (AVPixelFormat)m_AVPixelFormat, m_iWidth,
- m_iHeight, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
- }
-
- void FfmpegDecodeNew::run()
- {
- m_bNeedWork = true;
- unsigned short usRecvSize = 0;
- unsigned char* pVideoBuffer = new unsigned char[VideoPacketLength];
- int ret = 0;
- while (m_bNeedWork) {
- usRecvSize = m_pConstBuffer->read(pVideoBuffer, VideoPacketLength);
- if (usRecvSize <= 0) {
- continue;
- }
- unsigned char* pBuffer = pVideoBuffer;
- while (0 < usRecvSize) {
- // (8)获取AVPacket压缩数据
- ret = av_parser_parse2(m_pAVCodecParserContext, m_pAVCodecContext, &(m_pAVPacket->data),
- &(m_pAVPacket->size), pBuffer, usRecvSize, AV_NOPTS_VALUE,
- AV_NOPTS_VALUE, 0);
- if (ret < 0) {
- return;
- }
- pBuffer += ret;
- usRecvSize -= ret;
- if (m_pAVPacket->size) { // 说明获取到AVPacket压缩数据
- decode(m_pAVCodecContext, m_pAVFrameSrc, m_pAVPacket);
- }
- }
- }
- }
-
- void FfmpegDecodeNew::decode(AVCodecContext* pCodecContext, AVFrame* pFrame, AVPacket* pPacket)
- {
- // (9)发送AVPacket数据到Ffmepg,放到解码队列中
- int ret = avcodec_send_packet(pCodecContext, pPacket);
- if (ret < 0) {
- return;
- }
- while (0 <= ret) {
- // (10)从解码队列中取出1个AVFrame数据
- ret = avcodec_receive_frame(pCodecContext, pFrame);
- if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
- return;
- } else if (ret < 0) {
- return;
- }
- /*
- //验证一下是否可以根据pFrame对m_pAVFrameDes操作av_image_alloc和sws_getContext
- if (m_bSwsContext == false) {
- av_image_alloc(m_pAVFrameDes->data, m_pAVFrameDes->linesize, pFrame->width,
- pFrame->height, AV_PIX_FMT_RGB24, 1);
- //(12)初始化图像格式转换
- m_pSwsContext = sws_getContext(pFrame->width, pFrame->height,
- (AVPixelFormat)pFrame->format, pFrame->width, pFrame->height, AV_PIX_FMT_RGB24,
- SWS_FAST_BILINEAR, NULL, NULL, NULL); m_iWidth = pFrame->width; //图像宽度 m_iHeight =
- pFrame->height; //图像高度 m_bSwsContext = true;
- }
- if (m_bSwsContext == true) {
- // (13) 进行图像格式转换
- sws_scale(m_pSwsContext, m_pAVFrameSrc->data, m_pAVFrameSrc->linesize, 0,
- m_pAVFrameSrc->height, m_pAVFrameDes->data, m_pAVFrameDes->linesize);
- //(14)对转换后的数据进行处理
- m_bImageUpdated = true;
- m_image = QImage((uchar*)m_pAVFrameDes->data[0],
- m_iWidth,m_iHeight,QImage::Format_RGB888);
- }
- */
-
- // (13) 进行图像格式转换
- sws_scale(m_pSwsContext, pFrame->data, pFrame->linesize, 0, pCodecContext->height,
- m_pAVFrameDes->data, m_pAVFrameDes->linesize);
- // (14)对转换后的数据进行处理
- QMutexLocker locker(&m_mutex);
- m_bImageUpdated = true;
- m_image =
- QImage((uchar*)m_pAVFrameDes->data[0], m_iWidth, m_iHeight, QImage::Format_RGB888);
- }
- }
-
- bool FfmpegDecodeNew::getImage(QImage& image)
- {
- QMutexLocker locker(&m_mutex);
- if (m_bImageUpdated) {
- image = m_image;
- m_bImageUpdated = false;
- return true;
- }
- return false;
- }
|