mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-03-09 23:50:56 +08:00
154 lines
5.7 KiB
C++
154 lines
5.7 KiB
C++
/*
|
|
* 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 "VpxRtmp.h"
|
|
#include "Rtmp/utils.h"
|
|
#include "Common/config.h"
|
|
#include "Extension/Factory.h"
|
|
using namespace std;
|
|
using namespace toolkit;
|
|
|
|
namespace mediakit {
|
|
|
|
void VpxRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt) {
|
|
if (_info.codec == CodecInvalid) {
|
|
// First, determine if it is an enhanced rtmp
|
|
parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info);
|
|
}
|
|
|
|
if (_info.is_enhanced) {
|
|
// Enhanced rtmp
|
|
parseVideoRtmpPacket((uint8_t *)pkt->data(), pkt->size(), &_info);
|
|
if (!_info.is_enhanced || _info.codec != getTrack()->getCodecId()) {
|
|
throw std::invalid_argument("Invalid enhanced-rtmp packet!");
|
|
}
|
|
|
|
auto data = (uint8_t *)pkt->data() + RtmpPacketInfo::kEnhancedRtmpHeaderSize;
|
|
auto size = pkt->size() - RtmpPacketInfo::kEnhancedRtmpHeaderSize;
|
|
switch (_info.video.pkt_type) {
|
|
case RtmpPacketType::PacketTypeSequenceStart: {
|
|
getTrack()->setExtraData(data, size);
|
|
break;
|
|
}
|
|
|
|
case RtmpPacketType::PacketTypeCodedFramesX:
|
|
case RtmpPacketType::PacketTypeCodedFrames: {
|
|
auto pts = pkt->time_stamp;
|
|
if (RtmpPacketType::PacketTypeCodedFrames == _info.video.pkt_type) {
|
|
CHECK_RET(size > 3);
|
|
// SI24 = [CompositionTime Offset]
|
|
int32_t cts = (load_be24(data) + 0xff800000) ^ 0xff800000;
|
|
pts += cts;
|
|
data += 3;
|
|
size -= 3;
|
|
}
|
|
outputFrame((char*)data, size, pkt->time_stamp, pts);
|
|
break;
|
|
}
|
|
default:
|
|
WarnL << "Unknown pkt_type: " << (int)_info.video.pkt_type;
|
|
break;
|
|
}
|
|
} else {
|
|
CHECK_RET(pkt->size() > 5);
|
|
uint8_t *cts_ptr = (uint8_t *)(pkt->buffer.data() + 2);
|
|
int32_t cts = (load_be24(cts_ptr) + 0xff800000) ^ 0xff800000;
|
|
// 国内扩展(12) Vpx rtmp
|
|
if (pkt->isConfigFrame()) {
|
|
getTrack()->setExtraData((uint8_t *)pkt->data() + 5, pkt->size() - 5);
|
|
} else {
|
|
outputFrame(pkt->data() + 5, pkt->size() - 5, pkt->time_stamp, pkt->time_stamp + cts);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VpxRtmpDecoder::outputFrame(const char *data, size_t size, uint32_t dts, uint32_t pts) {
|
|
RtmpCodec::inputFrame(Factory::getFrameFromPtr(getTrack()->getCodecId(), data, size, dts, pts));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
VpxRtmpEncoder::VpxRtmpEncoder(const Track::Ptr &track) : RtmpCodec(track) {
|
|
_enhanced = mINI::Instance()[Rtmp::kEnhanced];
|
|
}
|
|
|
|
bool VpxRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
|
|
auto packet = RtmpPacket::create();
|
|
packet->buffer.resize(8 + frame->size());
|
|
char *buff = packet->data();
|
|
int32_t cts = frame->pts() - frame->dts();
|
|
if (_enhanced) {
|
|
auto header = (RtmpVideoHeaderEnhanced *)buff;
|
|
header->enhanced = 1;
|
|
header->frame_type = frame->keyFrame() ? (int)RtmpFrameType::key_frame : (int)RtmpFrameType::inter_frame;
|
|
header->fourcc = htonl(getCodecFourCC(frame->getCodecId()));
|
|
buff += RtmpPacketInfo::kEnhancedRtmpHeaderSize;
|
|
if (cts) {
|
|
header->pkt_type = (uint8_t)RtmpPacketType::PacketTypeCodedFrames;
|
|
set_be24(buff, cts);
|
|
buff += 3;
|
|
} else {
|
|
header->pkt_type = (uint8_t)RtmpPacketType::PacketTypeCodedFramesX;
|
|
}
|
|
} else {
|
|
// flags
|
|
uint8_t flags = getCodecFlags(frame->getCodecId());
|
|
flags |= (uint8_t)(frame->keyFrame() ? RtmpFrameType::key_frame : RtmpFrameType::inter_frame) << 4;
|
|
|
|
buff[0] = flags;
|
|
buff[1] = (uint8_t)RtmpH264PacketType::h264_nalu;
|
|
// cts
|
|
set_be24(&buff[2], cts);
|
|
buff += 5;
|
|
}
|
|
|
|
packet->time_stamp = frame->dts();
|
|
memcpy(buff, frame->data(), frame->size());
|
|
buff += frame->size();
|
|
packet->body_size = buff - packet->data();
|
|
packet->chunk_id = CHUNK_VIDEO;
|
|
packet->stream_index = STREAM_MEDIA;
|
|
packet->type_id = MSG_VIDEO;
|
|
// Output rtmp packet
|
|
RtmpCodec::inputRtmp(packet);
|
|
return true;
|
|
}
|
|
|
|
void VpxRtmpEncoder::makeConfigPacket() {
|
|
auto extra_data = getTrack()->getExtraData();
|
|
if (!extra_data || !extra_data->size())
|
|
return;
|
|
auto pkt = RtmpPacket::create();
|
|
pkt->body_size = 5 + extra_data->size();
|
|
pkt->buffer.resize(pkt->body_size);
|
|
auto buff = pkt->buffer.data();
|
|
if (_enhanced) {
|
|
auto header = (RtmpVideoHeaderEnhanced *)buff;
|
|
header->enhanced = 1;
|
|
header->pkt_type = (int)RtmpPacketType::PacketTypeSequenceStart;
|
|
header->frame_type = (int)RtmpFrameType::key_frame;
|
|
header->fourcc = htonl(getCodecFourCC(getTrack()->getCodecId()));
|
|
} else {
|
|
uint8_t flags = getCodecFlags(getTrack()->getCodecId());
|
|
flags |= ((uint8_t)RtmpFrameType::key_frame << 4);
|
|
buff[0] = flags;
|
|
buff[1] = (uint8_t)RtmpH264PacketType::h264_config_header;
|
|
// cts
|
|
memset(buff + 2, 0, 3);
|
|
}
|
|
memcpy(buff+5, extra_data->data(), extra_data->size());
|
|
pkt->chunk_id = CHUNK_VIDEO;
|
|
pkt->stream_index = STREAM_MEDIA;
|
|
pkt->time_stamp = 0;
|
|
pkt->type_id = MSG_VIDEO;
|
|
RtmpCodec::inputRtmp(pkt);
|
|
}
|
|
|
|
} // namespace mediakit
|