1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Shenzhen Kaihong DID Co., Ltd. 3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License. 5094332d3Sopenharmony_ci * You may obtain a copy of the License at 6094332d3Sopenharmony_ci * 7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8094332d3Sopenharmony_ci * 9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and 13094332d3Sopenharmony_ci * limitations under the License. 14094332d3Sopenharmony_ci */ 15094332d3Sopenharmony_ci#include "codec_packet_reader.h" 16094332d3Sopenharmony_ci#include <arpa/inet.h> 17094332d3Sopenharmony_ci#include <hdf_log.h> 18094332d3Sopenharmony_cinamespace { 19094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_ONE = -1; 20094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_SEC = -2; 21094332d3Sopenharmony_ciconstexpr int32_t START_CODE_OFFSET_THIRD = -3; 22094332d3Sopenharmony_ciconstexpr int32_t START_CODE_SIZE_FRAME = 4; 23094332d3Sopenharmony_ciconstexpr int32_t START_CODE_SIZE_SLICE = 3; 24094332d3Sopenharmony_ciconstexpr char START_CODE = 0x1; 25094332d3Sopenharmony_ciconstexpr char VOP_START = 0xB6; 26094332d3Sopenharmony_ci} // namespace 27094332d3Sopenharmony_ci 28094332d3Sopenharmony_ciCodecPacketReader::Ptr CodecPacketReader::GetPacketReader(const CodecMime &mime) 29094332d3Sopenharmony_ci{ 30094332d3Sopenharmony_ci CodecPacketReader::Ptr reader = nullptr; 31094332d3Sopenharmony_ci switch (mime) { 32094332d3Sopenharmony_ci case CodecMime::AVC: 33094332d3Sopenharmony_ci case CodecMime::HEVC: 34094332d3Sopenharmony_ci reader = std::make_shared<CodecH264Reader>(); 35094332d3Sopenharmony_ci break; 36094332d3Sopenharmony_ci case CodecMime::MPEG4: 37094332d3Sopenharmony_ci reader = std::make_shared<CodecMpeg4Reader>(); 38094332d3Sopenharmony_ci break; 39094332d3Sopenharmony_ci case CodecMime::VP9: 40094332d3Sopenharmony_ci reader = std::make_shared<CodecVp9Reader>(); 41094332d3Sopenharmony_ci break; 42094332d3Sopenharmony_ci default: 43094332d3Sopenharmony_ci break; 44094332d3Sopenharmony_ci } 45094332d3Sopenharmony_ci return reader; 46094332d3Sopenharmony_ci} 47094332d3Sopenharmony_ci 48094332d3Sopenharmony_ciCodecH264Reader::CodecH264Reader() : CodecPacketReader() 49094332d3Sopenharmony_ci{} 50094332d3Sopenharmony_ci 51094332d3Sopenharmony_cibool CodecH264Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 52094332d3Sopenharmony_ci{ 53094332d3Sopenharmony_ci // read start code first 54094332d3Sopenharmony_ci ioIn.read(buf, START_CODE_SIZE_FRAME); 55094332d3Sopenharmony_ci if (ioIn.eof()) { 56094332d3Sopenharmony_ci return true; 57094332d3Sopenharmony_ci } 58094332d3Sopenharmony_ci 59094332d3Sopenharmony_ci char *temp = buf; 60094332d3Sopenharmony_ci temp += START_CODE_SIZE_FRAME; 61094332d3Sopenharmony_ci bool ret = true; 62094332d3Sopenharmony_ci while (!ioIn.eof()) { 63094332d3Sopenharmony_ci ioIn.read(temp, 1); 64094332d3Sopenharmony_ci if (*temp == START_CODE) { 65094332d3Sopenharmony_ci // check start code 66094332d3Sopenharmony_ci if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) && 67094332d3Sopenharmony_ci (temp[START_CODE_OFFSET_THIRD] == 0)) { 68094332d3Sopenharmony_ci ioIn.seekg(-START_CODE_SIZE_FRAME, std::ios_base::cur); 69094332d3Sopenharmony_ci temp -= (START_CODE_SIZE_FRAME - 1); 70094332d3Sopenharmony_ci ret = false; 71094332d3Sopenharmony_ci break; 72094332d3Sopenharmony_ci } else if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) { 73094332d3Sopenharmony_ci ioIn.seekg(-START_CODE_SIZE_SLICE, std::ios_base::cur); 74094332d3Sopenharmony_ci temp -= (START_CODE_SIZE_SLICE - 1); 75094332d3Sopenharmony_ci ret = false; 76094332d3Sopenharmony_ci break; 77094332d3Sopenharmony_ci } 78094332d3Sopenharmony_ci } 79094332d3Sopenharmony_ci temp++; 80094332d3Sopenharmony_ci } 81094332d3Sopenharmony_ci filledCount = (temp - buf); 82094332d3Sopenharmony_ci return ret; 83094332d3Sopenharmony_ci} 84094332d3Sopenharmony_ci 85094332d3Sopenharmony_ciCodecMpeg4Reader::CodecMpeg4Reader() : CodecPacketReader() 86094332d3Sopenharmony_ci{} 87094332d3Sopenharmony_ci 88094332d3Sopenharmony_cibool CodecMpeg4Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 89094332d3Sopenharmony_ci{ 90094332d3Sopenharmony_ci ioIn.read(buf, START_CODE_SIZE_SLICE); 91094332d3Sopenharmony_ci if (ioIn.eof()) { 92094332d3Sopenharmony_ci return true; 93094332d3Sopenharmony_ci } 94094332d3Sopenharmony_ci 95094332d3Sopenharmony_ci char *temp = buf; 96094332d3Sopenharmony_ci temp += START_CODE_SIZE_SLICE; 97094332d3Sopenharmony_ci bool ret = true; 98094332d3Sopenharmony_ci bool findVop = false; 99094332d3Sopenharmony_ci while (!ioIn.eof()) { 100094332d3Sopenharmony_ci ioIn.read(temp, 1); 101094332d3Sopenharmony_ci // check start code 102094332d3Sopenharmony_ci if ((*temp == VOP_START) && (temp[START_CODE_OFFSET_ONE] == START_CODE) && (temp[START_CODE_OFFSET_SEC] == 0) && 103094332d3Sopenharmony_ci (temp[START_CODE_OFFSET_THIRD] == 0)) { 104094332d3Sopenharmony_ci findVop = true; 105094332d3Sopenharmony_ci } 106094332d3Sopenharmony_ci if (findVop && (*temp == START_CODE) && (temp[START_CODE_OFFSET_ONE] == 0) && 107094332d3Sopenharmony_ci (temp[START_CODE_OFFSET_SEC] == 0)) { 108094332d3Sopenharmony_ci temp -= START_CODE_SIZE_SLICE - 1; 109094332d3Sopenharmony_ci ioIn.seekg(START_CODE_OFFSET_THIRD, std::ios_base::cur); 110094332d3Sopenharmony_ci ret = false; 111094332d3Sopenharmony_ci break; 112094332d3Sopenharmony_ci } 113094332d3Sopenharmony_ci temp++; 114094332d3Sopenharmony_ci } 115094332d3Sopenharmony_ci filledCount = (temp - buf); 116094332d3Sopenharmony_ci return ret; 117094332d3Sopenharmony_ci} 118094332d3Sopenharmony_ci 119094332d3Sopenharmony_ciCodecVp9Reader::CodecVp9Reader() : CodecPacketReader() 120094332d3Sopenharmony_ci{} 121094332d3Sopenharmony_ci 122094332d3Sopenharmony_cibool CodecVp9Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 123094332d3Sopenharmony_ci{ 124094332d3Sopenharmony_ci // vp9 saved in trunk, use ffmpeg to save vp9 to .vp9 file, the format like this: 125094332d3Sopenharmony_ci // len(4 bytes, little-end, length of vp9 data) + vp9 data 126094332d3Sopenharmony_ci filledCount = 0; 127094332d3Sopenharmony_ci ioIn.read(reinterpret_cast<char *>(&filledCount), sizeof(filledCount)); 128094332d3Sopenharmony_ci if (ioIn.eof()) { 129094332d3Sopenharmony_ci return true; 130094332d3Sopenharmony_ci } 131094332d3Sopenharmony_ci filledCount = ntohl(filledCount); 132094332d3Sopenharmony_ci ioIn.read(buf, filledCount); 133094332d3Sopenharmony_ci if (ioIn.eof()) { 134094332d3Sopenharmony_ci return true; 135094332d3Sopenharmony_ci } 136094332d3Sopenharmony_ci return false; 137094332d3Sopenharmony_ci}