1e0e9324cSopenharmony_ci/* 2e0e9324cSopenharmony_ci * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3e0e9324cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0e9324cSopenharmony_ci * you may not use this file except in compliance with the License. 5e0e9324cSopenharmony_ci * You may obtain a copy of the License at 6e0e9324cSopenharmony_ci * 7e0e9324cSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0e9324cSopenharmony_ci * 9e0e9324cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0e9324cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0e9324cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0e9324cSopenharmony_ci * See the License for the specific language governing permissions and 13e0e9324cSopenharmony_ci * limitations under the License. 14e0e9324cSopenharmony_ci */ 15e0e9324cSopenharmony_ci 16e0e9324cSopenharmony_ci#include "frame_merger.h" 17e0e9324cSopenharmony_ci#include <arpa/inet.h> 18e0e9324cSopenharmony_ci#include "common/common_macro.h" 19e0e9324cSopenharmony_ci 20e0e9324cSopenharmony_cinamespace OHOS { 21e0e9324cSopenharmony_cinamespace Sharing { 22e0e9324cSopenharmony_cistatic size_t constexpr MAX_FRAME_CACHE_SIZE = 100; 23e0e9324cSopenharmony_ci 24e0e9324cSopenharmony_civoid FrameMerger::Clear() 25e0e9324cSopenharmony_ci{ 26e0e9324cSopenharmony_ci frameCache_.clear(); 27e0e9324cSopenharmony_ci haveDecodeAbleFrame_ = false; 28e0e9324cSopenharmony_ci} 29e0e9324cSopenharmony_ci 30e0e9324cSopenharmony_civoid FrameMerger::SetType(int32_t type) 31e0e9324cSopenharmony_ci{ 32e0e9324cSopenharmony_ci type_ = type; 33e0e9324cSopenharmony_ci} 34e0e9324cSopenharmony_ci 35e0e9324cSopenharmony_cibool FrameMerger::InputFrame(const Frame::Ptr &frame, DataBuffer::Ptr &buffer, const onOutput &cb) 36e0e9324cSopenharmony_ci{ 37e0e9324cSopenharmony_ci if (buffer == nullptr) { 38e0e9324cSopenharmony_ci return false; 39e0e9324cSopenharmony_ci } 40e0e9324cSopenharmony_ci RETURN_FALSE_IF_NULL(buffer); 41e0e9324cSopenharmony_ci 42e0e9324cSopenharmony_ci if (WillFlush(frame)) { 43e0e9324cSopenharmony_ci if (frameCache_.empty()) { 44e0e9324cSopenharmony_ci return false; 45e0e9324cSopenharmony_ci } 46e0e9324cSopenharmony_ci Frame::Ptr back = frameCache_.back(); 47e0e9324cSopenharmony_ci RETURN_FALSE_IF_NULL(back); 48e0e9324cSopenharmony_ci bool haveKeyFrame = back->KeyFrame(); 49e0e9324cSopenharmony_ci if (frameCache_.size() != 1 || type_ == MP4_NAL_SIZE || buffer) { 50e0e9324cSopenharmony_ci DataBuffer::Ptr &merged = buffer; 51e0e9324cSopenharmony_ci 52e0e9324cSopenharmony_ci for (auto &&vframe : frameCache_) { 53e0e9324cSopenharmony_ci DoMerge(merged, vframe); 54e0e9324cSopenharmony_ci if (vframe->KeyFrame()) { 55e0e9324cSopenharmony_ci haveKeyFrame = true; 56e0e9324cSopenharmony_ci } 57e0e9324cSopenharmony_ci } 58e0e9324cSopenharmony_ci } 59e0e9324cSopenharmony_ci cb(back->Dts(), back->Pts(), buffer, haveKeyFrame); 60e0e9324cSopenharmony_ci frameCache_.clear(); 61e0e9324cSopenharmony_ci haveDecodeAbleFrame_ = false; 62e0e9324cSopenharmony_ci } 63e0e9324cSopenharmony_ci 64e0e9324cSopenharmony_ci if (!frame) { 65e0e9324cSopenharmony_ci return false; 66e0e9324cSopenharmony_ci } 67e0e9324cSopenharmony_ci 68e0e9324cSopenharmony_ci if (frame->DecodeAble()) { 69e0e9324cSopenharmony_ci haveDecodeAbleFrame_ = true; 70e0e9324cSopenharmony_ci } 71e0e9324cSopenharmony_ci frameCache_.emplace_back(frame); 72e0e9324cSopenharmony_ci return true; 73e0e9324cSopenharmony_ci} 74e0e9324cSopenharmony_ci 75e0e9324cSopenharmony_cibool FrameMerger::WillFlush(const Frame::Ptr &frame) const 76e0e9324cSopenharmony_ci{ 77e0e9324cSopenharmony_ci if (frameCache_.empty()) { 78e0e9324cSopenharmony_ci return false; 79e0e9324cSopenharmony_ci } 80e0e9324cSopenharmony_ci if (!frame) { 81e0e9324cSopenharmony_ci return true; 82e0e9324cSopenharmony_ci } 83e0e9324cSopenharmony_ci switch (type_) { 84e0e9324cSopenharmony_ci case NONE: { 85e0e9324cSopenharmony_ci bool newFrame = false; 86e0e9324cSopenharmony_ci switch (frame->GetCodecId()) { 87e0e9324cSopenharmony_ci case CODEC_H264: 88e0e9324cSopenharmony_ci case CODEC_H265: { 89e0e9324cSopenharmony_ci newFrame = frame->PrefixSize(); 90e0e9324cSopenharmony_ci break; 91e0e9324cSopenharmony_ci } 92e0e9324cSopenharmony_ci default: 93e0e9324cSopenharmony_ci break; 94e0e9324cSopenharmony_ci } 95e0e9324cSopenharmony_ci 96e0e9324cSopenharmony_ci return newFrame || frameCache_.back()->Dts() != frame->Dts() || frameCache_.size() > MAX_FRAME_CACHE_SIZE; 97e0e9324cSopenharmony_ci } 98e0e9324cSopenharmony_ci 99e0e9324cSopenharmony_ci case MP4_NAL_SIZE: 100e0e9324cSopenharmony_ci case H264_PREFIX: { 101e0e9324cSopenharmony_ci if (!haveDecodeAbleFrame_) { 102e0e9324cSopenharmony_ci return frameCache_.size() > MAX_FRAME_CACHE_SIZE; 103e0e9324cSopenharmony_ci } 104e0e9324cSopenharmony_ci if (frameCache_.back()->Dts() != frame->Dts() || frame->DecodeAble() || frame->ConfigFrame()) { 105e0e9324cSopenharmony_ci return true; 106e0e9324cSopenharmony_ci } 107e0e9324cSopenharmony_ci 108e0e9324cSopenharmony_ci return frameCache_.size() > MAX_FRAME_CACHE_SIZE; 109e0e9324cSopenharmony_ci } 110e0e9324cSopenharmony_ci default: 111e0e9324cSopenharmony_ci return false; 112e0e9324cSopenharmony_ci } 113e0e9324cSopenharmony_ci} 114e0e9324cSopenharmony_ci 115e0e9324cSopenharmony_civoid FrameMerger::DoMerge(DataBuffer::Ptr &merged, const Frame::Ptr &frame) const 116e0e9324cSopenharmony_ci{ 117e0e9324cSopenharmony_ci RETURN_IF_NULL(merged); 118e0e9324cSopenharmony_ci RETURN_IF_NULL(frame); 119e0e9324cSopenharmony_ci switch (type_) { 120e0e9324cSopenharmony_ci case NONE: { 121e0e9324cSopenharmony_ci merged->Append(frame->Data(), frame->Size()); 122e0e9324cSopenharmony_ci break; 123e0e9324cSopenharmony_ci } 124e0e9324cSopenharmony_ci case H264_PREFIX: { 125e0e9324cSopenharmony_ci if (frame->PrefixSize()) { 126e0e9324cSopenharmony_ci merged->Append(frame->Data(), frame->Size()); 127e0e9324cSopenharmony_ci } else { 128e0e9324cSopenharmony_ci merged->Append("\x00\x00\x00\x01", 4); // 4:avc start code size 129e0e9324cSopenharmony_ci merged->Append(frame->Data(), frame->Size()); 130e0e9324cSopenharmony_ci } 131e0e9324cSopenharmony_ci break; 132e0e9324cSopenharmony_ci } 133e0e9324cSopenharmony_ci case MP4_NAL_SIZE: { 134e0e9324cSopenharmony_ci uint32_t naluSize = (uint32_t)(frame->Size() - frame->PrefixSize()); 135e0e9324cSopenharmony_ci naluSize = htonl(naluSize); 136e0e9324cSopenharmony_ci merged->Append((char *)&naluSize, 4); // 4:avc start code size 137e0e9324cSopenharmony_ci merged->Append(frame->Data() + frame->PrefixSize(), frame->Size() - frame->PrefixSize()); 138e0e9324cSopenharmony_ci break; 139e0e9324cSopenharmony_ci } 140e0e9324cSopenharmony_ci default: 141e0e9324cSopenharmony_ci break; 142e0e9324cSopenharmony_ci } 143e0e9324cSopenharmony_ci} 144e0e9324cSopenharmony_ci} // namespace Sharing 145e0e9324cSopenharmony_ci} // namespace OHOS