Files
ZLMediaKit/src/Record/MPEG.cpp

156 lines
4.9 KiB
C++
Raw Normal View History

2021-12-28 21:04:53 +08:00
/*
2023-12-09 16:23:51 +08:00
* Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
2021-12-28 21:04:53 +08:00
*
2023-12-09 16:23:51 +08:00
* This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
2021-12-28 21:04:53 +08:00
*
2023-12-09 16:23:51 +08:00
* Use of this source code is governed by MIT-like license that can be found in the
2021-12-28 21:04:53 +08:00
* 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 <assert.h>
2021-12-28 21:04:53 +08:00
#include "MPEG.h"
#if defined(ENABLE_HLS) || defined(ENABLE_RTPPROXY)
2022-11-12 21:59:48 +08:00
#include "mpeg-ts.h"
2021-12-29 14:18:52 +08:00
#include "mpeg-muxer.h"
2021-12-28 21:04:53 +08:00
using namespace toolkit;
2023-12-09 22:34:22 +08:00
namespace mediakit {
2021-12-28 21:04:53 +08:00
MpegMuxer::MpegMuxer(bool is_ps) {
_is_ps = is_ps;
createContext();
_buffer_pool.setSize(64);
2021-12-28 21:04:53 +08:00
}
MpegMuxer::~MpegMuxer() {
releaseContext();
}
bool MpegMuxer::addTrack(const Track::Ptr &track) {
2023-12-09 16:23:51 +08:00
auto mpeg_id = getMpegIdByCodec(track->getCodecId());
if (mpeg_id == PSI_STREAM_RESERVED) {
WarnL << "Unsupported codec: " << track->getCodecName();
return false;
2021-12-28 21:04:53 +08:00
}
2023-12-09 16:23:51 +08:00
if (track->getTrackType() == TrackVideo) {
_have_video = true;
}
2023-12-09 22:34:22 +08:00
_tracks[track->getIndex()].track_id = mpeg_muxer_add_stream((::mpeg_muxer_t *)_context, mpeg_id, nullptr, 0);
2023-12-09 16:23:51 +08:00
return true;
2021-12-28 21:04:53 +08:00
}
bool MpegMuxer::inputFrame(const Frame::Ptr &frame) {
2023-12-09 22:34:22 +08:00
auto it = _tracks.find(frame->getIndex());
if (it == _tracks.end()) {
2021-12-28 21:04:53 +08:00
return false;
}
2023-12-09 22:34:22 +08:00
auto &track = it->second;
2021-12-28 21:04:53 +08:00
_key_pos = !_have_video;
switch (frame->getCodecId()) {
case CodecH264:
case CodecH265: {
2023-12-09 22:34:22 +08:00
// 这里的代码逻辑是让SPS、PPS、IDR这些时间戳相同的帧打包到一起当做一个帧处理
return track.merger.inputFrame(frame, [&](uint64_t dts, uint64_t pts, const Buffer::Ptr &buffer, bool have_idr) {
2021-12-28 21:04:53 +08:00
_key_pos = have_idr;
2023-12-09 22:34:22 +08:00
// 取视频时间戳为TS的时间戳
2022-08-08 17:13:39 +08:00
_timestamp = dts;
2022-01-06 15:30:09 +08:00
_max_cache_size = 512 + 1.2 * buffer->size();
2023-12-09 22:34:22 +08:00
mpeg_muxer_input((::mpeg_muxer_t *)_context, track.track_id, have_idr ? 0x0001 : 0, pts * 90LL, dts * 90LL, buffer->data(), buffer->size());
2022-01-06 15:30:09 +08:00
flushCache();
2021-12-28 21:04:53 +08:00
});
}
case CodecAAC: {
2023-12-09 16:23:51 +08:00
CHECK(frame->prefixSize(), "Mpeg muxer required aac frame with adts heade");
2021-12-28 21:04:53 +08:00
}
default: {
if (!_have_video) {
2023-12-09 16:23:51 +08:00
// 没有视频时才以音频时间戳为TS的时间戳
2022-08-08 17:13:39 +08:00
_timestamp = frame->dts();
2021-12-28 21:04:53 +08:00
}
2023-12-09 16:23:51 +08:00
if (frame->getTrackType() == TrackType::TrackVideo) {
_key_pos = frame->keyFrame();
_timestamp = frame->dts();
}
2022-01-06 15:30:09 +08:00
_max_cache_size = 512 + 1.2 * frame->size();
2023-12-09 22:34:22 +08:00
mpeg_muxer_input((::mpeg_muxer_t *)_context, track.track_id, frame->keyFrame() ? 0x0001 : 0, frame->pts() * 90LL, frame->dts() * 90LL, frame->data(), frame->size());
2022-01-06 15:30:09 +08:00
flushCache();
2021-12-28 21:04:53 +08:00
return true;
}
}
}
void MpegMuxer::resetTracks() {
_have_video = false;
//通知片段中断
onWrite(nullptr, _timestamp, false);
releaseContext();
createContext();
}
void MpegMuxer::createContext() {
static mpeg_muxer_func_t func = {
/*alloc*/
[](void *param, size_t bytes) {
2022-01-06 15:30:09 +08:00
MpegMuxer *thiz = (MpegMuxer *)param;
if (!thiz->_current_buffer
|| thiz->_current_buffer->size() + bytes > thiz->_current_buffer->getCapacity()) {
if (thiz->_current_buffer) {
thiz->flushCache();
}
thiz->_current_buffer = thiz->_buffer_pool.obtain2();
thiz->_current_buffer->setSize(0);
thiz->_current_buffer->setCapacity(MAX(thiz->_max_cache_size, bytes));
}
return (void *)(thiz->_current_buffer->data() + thiz->_current_buffer->size());
2021-12-28 21:04:53 +08:00
},
/*free*/
[](void *param, void *packet) {
//什么也不做
},
/*wtite*/
[](void *param, int stream, void *packet, size_t bytes) {
MpegMuxer *thiz = (MpegMuxer *) param;
thiz->onWrite_l(packet, bytes);
return 0;
}
};
if (_context == nullptr) {
_context = (struct mpeg_muxer_t *)mpeg_muxer_create(_is_ps, &func, this);
2021-12-28 21:04:53 +08:00
}
}
void MpegMuxer::onWrite_l(const void *packet, size_t bytes) {
2022-01-06 15:30:09 +08:00
assert(_current_buffer && _current_buffer->data() + _current_buffer->size() == packet);
_current_buffer->setSize(_current_buffer->size() + bytes);
}
void MpegMuxer::flushCache() {
onWrite(std::move(_current_buffer), _timestamp, _key_pos);
2021-12-28 21:04:53 +08:00
_key_pos = false;
}
void MpegMuxer::releaseContext() {
if (_context) {
mpeg_muxer_destroy((::mpeg_muxer_t *)_context);
2021-12-28 21:04:53 +08:00
_context = nullptr;
}
2023-12-09 22:34:22 +08:00
_tracks.clear();
2021-12-28 21:04:53 +08:00
}
2022-10-16 19:49:56 +08:00
void MpegMuxer::flush() {
2023-12-09 22:34:22 +08:00
for (auto &pr : _tracks) {
pr.second.merger.flush();
}
2022-10-16 19:49:56 +08:00
}
2021-12-28 21:04:53 +08:00
}//mediakit
#endif