/* * 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 "RtmpCodec.h" #include "RtmpDemuxer.h" #include "Extension/Factory.h" using namespace std; namespace mediakit { size_t RtmpDemuxer::trackCount(const AMFValue &metadata) { size_t ret = 0; metadata.object_for_each([&](const string &key, const AMFValue &val) { if (key == "videocodecid") { // 找到视频 [AUTO-TRANSLATED:e66249fc] // Find video ++ret; return; } if (key == "audiocodecid") { // 找到音频 [AUTO-TRANSLATED:126ce656] // Find audio ++ret; return; } }); return ret; } bool RtmpDemuxer::loadMetaData(const AMFValue &val) { bool ret = false; try { int audiosamplerate = 0; int audiochannels = 0; int audiosamplesize = 0; int videodatarate = 0; int audiodatarate = 0; const AMFValue *audiocodecid = nullptr; const AMFValue *videocodecid = nullptr; val.object_for_each([&](const string &key, const AMFValue &val) { if (key == "duration") { _duration = (float)val.as_number(); return; } if (key == "audiosamplerate") { audiosamplerate = val.as_integer(); return; } if (key == "audiosamplesize") { audiosamplesize = val.as_integer(); return; } if (key == "stereo") { audiochannels = val.as_boolean() ? 2 : 1; return; } if (key == "videocodecid") { // 找到视频 [AUTO-TRANSLATED:e66249fc] // Find video videocodecid = &val; return; } if (key == "audiocodecid") { // 找到音频 [AUTO-TRANSLATED:126ce656] // Find audio audiocodecid = &val; return; } if (key == "audiodatarate") { audiodatarate = val.as_integer(); return; } if (key == "videodatarate") { videodatarate = val.as_integer(); return; } }); if (videocodecid) { // 有视频 [AUTO-TRANSLATED:8d6ad811] // Has video ret = true; makeVideoTrack(*videocodecid, videodatarate * 1024); } if (audiocodecid) { // 有音频 [AUTO-TRANSLATED:8f9ac7f1] // Has audio ret = true; makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize, audiodatarate * 1024); } } catch (std::exception &ex) { WarnL << ex.what(); } if (ret) { // metadata中存在track相关的描述,那么我们根据metadata判断有多少个track [AUTO-TRANSLATED:47e02e95] // If there is a track-related description in the metadata, we determine the number of tracks based on the metadata addTrackCompleted(); } return ret; } float RtmpDemuxer::getDuration() const { return _duration; } void RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) { switch (pkt->type_id) { case MSG_VIDEO: { if (!_try_get_video_track) { _try_get_video_track = true; auto codec_id = parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size()); makeVideoTrack(Factory::getTrackByCodecId(codec_id), 0); } if (_video_rtmp_decoder) { _video_rtmp_decoder->inputRtmp(pkt); } break; } case MSG_AUDIO: { if (!_try_get_audio_track) { _try_get_audio_track = true; auto codec = AMFValue(pkt->getRtmpCodecId()); makeAudioTrack(codec, pkt->getAudioSampleRate(), pkt->getAudioChannel(), pkt->getAudioSampleBit(), 0); } if (_audio_rtmp_decoder) { _audio_rtmp_decoder->inputRtmp(pkt); } break; } default: break; } } void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec, int bit_rate) { makeVideoTrack(Factory::getVideoTrackByAmf(videoCodec), bit_rate); } void RtmpDemuxer::makeVideoTrack(const Track::Ptr &track, int bit_rate) { if (_video_rtmp_decoder) { return; } // 生成Track对象 [AUTO-TRANSLATED:8c7aee28] // Generate Track object _video_track = dynamic_pointer_cast(track); if (!_video_track) { return; } // 生成rtmpCodec对象以便解码rtmp [AUTO-TRANSLATED:a3c81353] // Generate rtmpCodec object to decode rtmp _video_rtmp_decoder = Factory::getRtmpDecoderByTrack(_video_track); if (!_video_rtmp_decoder) { // 找不到相应的rtmp解码器,该track无效 [AUTO-TRANSLATED:bbea0d74] // Cannot find the corresponding rtmp decoder, the track is invalid _video_track.reset(); return; } _video_track->setBitRate(bit_rate); addTrack(_video_track); _try_get_video_track = true; } void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec, int sample_rate, int channels, int sample_bit, int bit_rate) { if (_audio_rtmp_decoder) { return; } // 生成Track对象 [AUTO-TRANSLATED:8c7aee28] // Generate Track object _audio_track = dynamic_pointer_cast(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit)); if (!_audio_track) { return; } // 生成rtmpCodec对象以便解码rtmp [AUTO-TRANSLATED:a3c81353] // Generate rtmpCodec object to decode rtmp _audio_rtmp_decoder = Factory::getRtmpDecoderByTrack(_audio_track); if (!_audio_rtmp_decoder) { // 找不到相应的rtmp解码器,该track无效 [AUTO-TRANSLATED:bbea0d74] // Cannot find the corresponding rtmp decoder, the track is invalid _audio_track.reset(); return; } _audio_track->setBitRate(bit_rate); addTrack(_audio_track); _try_get_audio_track = true; } } /* namespace mediakit */