Older/MediaServer/Rtp/Decoder.cpp
amass 9de3af15eb
All checks were successful
Deploy / PullDocker (push) Successful in 12s
Deploy / Build (push) Successful in 1m51s
add ZLMediaKit code for learning.
2024-09-28 23:55:00 +08:00

161 lines
5.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
*
* Use of this source code is governed by MIT-like 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.
*/
#include "Decoder.h"
#include "PSDecoder.h"
#include "TSDecoder.h"
#include "Extension/Factory.h"
#if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS)
#include "mpeg-ts.h"
#endif
using namespace toolkit;
namespace mediakit {
void Decoder::setOnDecode(Decoder::onDecode cb) {
_on_decode = std::move(cb);
}
void Decoder::setOnStream(Decoder::onStream cb) {
_on_stream = std::move(cb);
}
static Decoder::Ptr createDecoder_l(DecoderImp::Type type) {
switch (type){
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;
}
}
/////////////////////////////////////////////////////////////
DecoderImp::Ptr DecoderImp::createDecoder(Type type, MediaSinkInterface *sink){
auto decoder = createDecoder_l(type);
if(!decoder){
return nullptr;
}
return DecoderImp::Ptr(new DecoderImp(decoder, sink));
}
void DecoderImp::flush() {
for (auto &pr : _tracks) {
pr.second.second.flush();
}
}
ssize_t DecoderImp::input(const uint8_t *data, size_t bytes){
return _decoder->input(data, bytes);
}
DecoderImp::DecoderImp(const Decoder::Ptr &decoder, MediaSinkInterface *sink){
_decoder = decoder;
_sink = sink;
_decoder->setOnDecode([this](int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) {
onDecode(stream, codecid, flags, pts, dts, data, bytes);
});
_decoder->setOnStream([this](int stream, int codecid, const void *extra, size_t bytes, int finish) {
onStream(stream, codecid, extra, bytes, finish);
});
}
#if defined(ENABLE_RTPPROXY) || defined(ENABLE_HLS)
void DecoderImp::onStream(int stream, int codecid, const void *extra, size_t bytes, int finish) {
if (_finished) {
return;
}
// G711传统只支持 8000/1/16的规格FFmpeg貌似做了扩展但是这里不管它了 [AUTO-TRANSLATED:851813f7]
// G711 traditionally only supports the 8000/1/16 specification. FFmpeg seems to have extended it, but we'll ignore that here.
auto track = Factory::getTrackByCodecId(getCodecByMpegId(codecid), 8000, 1, 16);
if (track) {
onTrack(stream, std::move(track));
}
// 防止未获取视频track提前complete导致忽略后续视频的问题用于兼容一些不太规范的ps流 [AUTO-TRANSLATED:d6b349b5]
// Prevent the problem of ignoring subsequent video due to premature completion of the video track before it is obtained. This is used to be compatible with some non-standard PS streams.
if (finish && _have_video) {
_finished = true;
_sink->addTrackCompleted();
InfoL << "Add track finished";
}
}
void DecoderImp::onDecode(int stream, int codecid, int flags, int64_t pts, int64_t dts, const void *data, size_t bytes) {
pts /= 90;
dts /= 90;
auto codec = getCodecByMpegId(codecid);
if (codec == CodecInvalid) {
return;
}
auto &ref = _tracks[stream];
if (!ref.first) {
onTrack(stream, Factory::getTrackByCodecId(codec, 8000, 1, 16));
}
if (!ref.first) {
WarnL << "Unsupported codec :" << getCodecName(codec);
return;
}
auto frame = Factory::getFrameFromPtr(codec, (char *)data, bytes, dts, pts);
if (getTrackType(codec) != TrackVideo) {
onFrame(stream, frame);
return;
}
ref.second.inputFrame(frame, [this, stream, codec](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool) {
onFrame(stream, Factory::getFrameFromBuffer(codec, buffer, dts, pts));
});
}
#else
void DecoderImp::onDecode(int stream,int codecid,int flags,int64_t pts,int64_t dts,const void *data,size_t bytes) {}
void DecoderImp::onStream(int stream,int codecid,const void *extra,size_t bytes,int finish) {}
#endif
void DecoderImp::onTrack(int index, const Track::Ptr &track) {
if (!track) {
return;
}
track->setIndex(index);
auto &ref = _tracks[index];
if (ref.first) {
WarnL << "Already existed a same track: " << index << ", codec: " << track->getCodecName();
return;
}
ref.first = track;
_sink->addTrack(track);
InfoL << "Got track: " << track->getCodecName();
_have_video = track->getTrackType() == TrackVideo ? true : _have_video;
}
void DecoderImp::onFrame(int index, const Frame::Ptr &frame) {
if (frame) {
frame->setIndex(index);
_sink->inputFrame(frame);
}
}
}//namespace mediakit