Decoder.cpp 7.49 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.
xiongziliang committed
9 10 11 12 13
 */

#include "Decoder.h"
#include "PSDecoder.h"
#include "TSDecoder.h"
14 15 16 17 18 19
#include "mpeg-ts-proto.h"
#include "Extension/H264.h"
#include "Extension/H265.h"
#include "Extension/AAC.h"
#include "Extension/G711.h"

xiongziliang committed
20
namespace mediakit {
21
static Decoder::Ptr createDecoder_l(DecoderImp::Type type) {
xiongziliang committed
22
    switch (type){
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
        case DecoderImp::decoder_ps:
#ifdef ENABLE_RTPPROXY
            return std::make_shared<PSDecoder>();
#else
            WarnL << "创建ps解复用器失败,请打开ENABLE_RTPPROXY然后重新编译";
            return nullptr;
#endif//ENABLE_RTPPROXY

        case DecoderImp::decoder_ts:
#ifdef ENABLE_HLS
            return std::make_shared<TSDecoder>();
#else
            WarnL << "创建mpegts解复用器失败,请打开ENABLE_HLS然后重新编译";
            return nullptr;
#endif//ENABLE_HLS

        default: return nullptr;
    }
}

/////////////////////////////////////////////////////////////

45
DecoderImp::Ptr DecoderImp::createDecoder(Type type, MediaSinkInterface *sink){
46 47 48 49 50 51 52 53 54 55 56
    auto decoder =  createDecoder_l(type);
    if(!decoder){
        return nullptr;
    }
    return DecoderImp::Ptr(new DecoderImp(decoder, sink));
}

int DecoderImp::input(const uint8_t *data, int bytes){
    return _decoder->input(data, bytes);
}

57
DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    _decoder = decoder;
    _sink = sink;
    _decoder->setOnDecode([this](int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes){
        onDecode(stream,codecid,flags,pts,dts,data,bytes);
    });
}

#define SWITCH_CASE(codec_id) case codec_id : return #codec_id
static const char *getCodecName(int codec_id) {
    switch (codec_id) {
        SWITCH_CASE(PSI_STREAM_MPEG1);
        SWITCH_CASE(PSI_STREAM_MPEG2);
        SWITCH_CASE(PSI_STREAM_AUDIO_MPEG1);
        SWITCH_CASE(PSI_STREAM_MP3);
        SWITCH_CASE(PSI_STREAM_AAC);
        SWITCH_CASE(PSI_STREAM_MPEG4);
        SWITCH_CASE(PSI_STREAM_MPEG4_AAC_LATM);
        SWITCH_CASE(PSI_STREAM_H264);
        SWITCH_CASE(PSI_STREAM_MPEG4_AAC);
        SWITCH_CASE(PSI_STREAM_H265);
        SWITCH_CASE(PSI_STREAM_AUDIO_AC3);
        SWITCH_CASE(PSI_STREAM_AUDIO_EAC3);
        SWITCH_CASE(PSI_STREAM_AUDIO_DTS);
        SWITCH_CASE(PSI_STREAM_VIDEO_DIRAC);
        SWITCH_CASE(PSI_STREAM_VIDEO_VC1);
        SWITCH_CASE(PSI_STREAM_VIDEO_SVAC);
        SWITCH_CASE(PSI_STREAM_AUDIO_SVAC);
        SWITCH_CASE(PSI_STREAM_AUDIO_G711A);
        SWITCH_CASE(PSI_STREAM_AUDIO_G711U);
        SWITCH_CASE(PSI_STREAM_AUDIO_G722);
        SWITCH_CASE(PSI_STREAM_AUDIO_G723);
        SWITCH_CASE(PSI_STREAM_AUDIO_G729);
        default : return "unknown codec";
    }
}

void FrameMerger::inputFrame(const Frame::Ptr &frame,const function<void(uint32_t dts,uint32_t pts,const Buffer::Ptr &buffer)> &cb){
    if (!_frameCached.empty() && _frameCached.back()->dts() != frame->dts()) {
        Frame::Ptr back = _frameCached.back();
        Buffer::Ptr merged_frame = back;
        if(_frameCached.size() != 1){
            string merged;
            _frameCached.for_each([&](const Frame::Ptr &frame){
                merged.append(frame->data(),frame->size());
            });
            merged_frame = std::make_shared<BufferString>(std::move(merged));
        }
        cb(back->dts(),back->pts(),merged_frame);
        _frameCached.clear();
    }
    _frameCached.emplace_back(Frame::getCacheAbleFrame(frame));
}

void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,int bytes) {
    pts /= 90;
    dts /= 90;

    switch (codecid) {
        case PSI_STREAM_H264: {
            if (!_codecid_video) {
                //获取到视频
                _codecid_video = codecid;
                InfoL<< "got video track: H264";
                auto track = std::make_shared<H264Track>();
                onTrack(track);
            }

            if (codecid != _codecid_video) {
                WarnL<< "video track change to H264 from codecid:" << getCodecName(_codecid_video);
                return;
            }

            auto frame = std::make_shared<H264FrameNoCacheAble>((char *) data, bytes, dts, pts,0);
            _merger.inputFrame(frame,[this](uint32_t dts, uint32_t pts, const Buffer::Ptr &buffer) {
132
                onFrame(std::make_shared<H264FrameNoCacheAble>(buffer->data(), buffer->size(), dts, pts, prefixSize(buffer->data(), buffer->size())));
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
            });
            break;
        }

        case PSI_STREAM_H265: {
            if (!_codecid_video) {
                //获取到视频
                _codecid_video = codecid;
                InfoL<< "got video track: H265";
                auto track = std::make_shared<H265Track>();
                onTrack(track);
            }
            if (codecid != _codecid_video) {
                WarnL<< "video track change to H265 from codecid:" << getCodecName(_codecid_video);
                return;
            }
            auto frame = std::make_shared<H265FrameNoCacheAble>((char *) data, bytes, dts, pts, 0);
            _merger.inputFrame(frame,[this](uint32_t dts, uint32_t pts, const Buffer::Ptr &buffer) {
151
                onFrame(std::make_shared<H265FrameNoCacheAble>(buffer->data(), buffer->size(), dts, pts, prefixSize(buffer->data(), buffer->size())));
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
            });
            break;
        }

        case PSI_STREAM_AAC: {
            if (!_codecid_audio) {
                //获取到音频
                _codecid_audio = codecid;
                InfoL<< "got audio track: AAC";
                auto track = std::make_shared<AACTrack>();
                onTrack(track);
            }

            if (codecid != _codecid_audio) {
                WarnL<< "audio track change to AAC from codecid:" << getCodecName(_codecid_audio);
                return;
            }
            onFrame(std::make_shared<AACFrameNoCacheAble>((char *) data, bytes, dts, 0, 7));
            break;
        }

        case PSI_STREAM_AUDIO_G711A:
        case PSI_STREAM_AUDIO_G711U: {
            auto codec = codecid  == PSI_STREAM_AUDIO_G711A ? CodecG711A : CodecG711U;
            if (!_codecid_audio) {
                //获取到音频
                _codecid_audio = codecid;
                InfoL<< "got audio track: G711";
                //G711传统只支持 8000/1/16的规格,FFmpeg貌似做了扩展,但是这里不管它了
                auto track = std::make_shared<G711Track>(codec, 8000, 1, 16);
                onTrack(track);
            }

            if (codecid != _codecid_audio) {
                WarnL<< "audio track change to G711 from codecid:" << getCodecName(_codecid_audio);
                return;
            }
            auto frame = std::make_shared<G711FrameNoCacheAble>((char *) data, bytes, dts);
            frame->setCodec(codec);
            onFrame(frame);
            break;
        }
        default:
            if(codecid != 0){
                WarnL<< "unsupported codec type:" << getCodecName(codecid) << " " << (int)codecid;
            }
            break;
xiongziliang committed
199 200 201
    }
}

202 203 204 205 206 207 208 209
void DecoderImp::onTrack(const Track::Ptr &track) {
    _sink->addTrack(track);
}

void DecoderImp::onFrame(const Frame::Ptr &frame) {
    _sink->inputFrame(frame);
}

xiongziliang committed
210
}//namespace mediakit