FFMpegDecoder.h 2.79 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
xiongziliang committed
3 4 5
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
xiongziliang committed
6 7 8
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
xzl committed
9 10 11 12 13 14 15
 */

#ifndef H264Decoder_H_
#define H264Decoder_H_
#include <string>
#include <memory>
#include <stdexcept>
xiongziliang committed
16
#include "Extension/Frame.h"
xzl committed
17 18 19 20 21 22 23 24 25 26 27 28
#ifdef __cplusplus
extern "C" {
#endif
//#include "libavutil/mathematics.h"
#include "libavcodec/avcodec.h"
//#include "libswscale/swscale.h"
#ifdef __cplusplus
}
#endif

using namespace std;

xiongziliang committed
29
namespace mediakit {
xzl committed
30

xiongziliang committed
31
class FFMpegDecoder{
xzl committed
32
public:
xiongziliang committed
33 34 35 36 37 38 39 40 41 42 43 44
    FFMpegDecoder(int codec_id){
        auto ff_codec_id = AV_CODEC_ID_H264;
        switch (codec_id){
            case CodecH264:
                ff_codec_id = AV_CODEC_ID_H264;
                break;
            case CodecH265:
                ff_codec_id = AV_CODEC_ID_H265;
                break;
            default:
                throw std::invalid_argument("不支持该编码格式");
        }
45
        avcodec_register_all();
xiongziliang committed
46
        AVCodec *pCodec = avcodec_find_decoder(ff_codec_id);
47
        if (!pCodec) {
xiongziliang committed
48
            throw std::runtime_error("未找到解码器");
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
        }
        m_pContext.reset(avcodec_alloc_context3(pCodec), [](AVCodecContext *pCtx) {
            avcodec_close(pCtx);
            avcodec_free_context(&pCtx);
        });
        if (!m_pContext) {
            throw std::runtime_error("创建解码器失败");
        }
        if (pCodec->capabilities & AV_CODEC_CAP_TRUNCATED) {
            /* we do not send complete frames */
            m_pContext->flags |= AV_CODEC_FLAG_TRUNCATED;
        }
        if(avcodec_open2(m_pContext.get(), pCodec, NULL)< 0){
            throw std::runtime_error("打开编码器失败");
        }
        m_pFrame.reset(av_frame_alloc(),[](AVFrame *pFrame){
            av_frame_free(&pFrame);
        });
        if (!m_pFrame) {
            throw std::runtime_error("创建帧缓存失败");
        }
    }
xiongziliang committed
71
    virtual ~FFMpegDecoder(void){}
72 73 74 75 76 77 78 79 80 81 82 83 84 85
    bool inputVideo(unsigned char* data,unsigned int dataSize,uint32_t ui32Stamp,AVFrame **ppFrame){
        AVPacket pkt;
        av_init_packet(&pkt);
        pkt.data = data;
        pkt.size = dataSize;
        pkt.dts = ui32Stamp;
        int iGotPicture ;
        auto iLen = avcodec_decode_video2(m_pContext.get(), m_pFrame.get(), &iGotPicture, &pkt);
        if (!iGotPicture || iLen < 0) {
            return false;
        }
        *ppFrame = m_pFrame.get();
        return true;
    }
xzl committed
86
private:
87 88
    std::shared_ptr<AVCodecContext> m_pContext;
    std::shared_ptr<AVFrame> m_pFrame;
xzl committed
89 90 91
};


xiongziliang committed
92
} /* namespace mediakit */
xzl committed
93 94 95 96

#endif /* H264Decoder_H_ */