1/* 2 * Copyright (c) 2022-2023 Shenzhen Kaihong DID Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "codec_packet_reader.h" 16#include <arpa/inet.h> 17#include <hdf_log.h> 18namespace { 19constexpr int32_t START_CODE_OFFSET_ONE = -1; 20constexpr int32_t START_CODE_OFFSET_SEC = -2; 21constexpr int32_t START_CODE_OFFSET_THIRD = -3; 22constexpr int32_t START_CODE_SIZE_FRAME = 4; 23constexpr int32_t START_CODE_SIZE_SLICE = 3; 24constexpr char START_CODE = 0x1; 25constexpr char VOP_START = 0xB6; 26} // namespace 27 28CodecPacketReader::Ptr CodecPacketReader::GetPacketReader(const CodecMime &mime) 29{ 30 CodecPacketReader::Ptr reader = nullptr; 31 switch (mime) { 32 case CodecMime::AVC: 33 case CodecMime::HEVC: 34 reader = std::make_shared<CodecH264Reader>(); 35 break; 36 case CodecMime::MPEG4: 37 reader = std::make_shared<CodecMpeg4Reader>(); 38 break; 39 case CodecMime::VP9: 40 reader = std::make_shared<CodecVp9Reader>(); 41 break; 42 default: 43 break; 44 } 45 return reader; 46} 47 48CodecH264Reader::CodecH264Reader() : CodecPacketReader() 49{} 50 51bool CodecH264Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 52{ 53 // read start code first 54 ioIn.read(buf, START_CODE_SIZE_FRAME); 55 if (ioIn.eof()) { 56 return true; 57 } 58 59 char *temp = buf; 60 temp += START_CODE_SIZE_FRAME; 61 bool ret = true; 62 while (!ioIn.eof()) { 63 ioIn.read(temp, 1); 64 if (*temp == START_CODE) { 65 // check start code 66 if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0) && 67 (temp[START_CODE_OFFSET_THIRD] == 0)) { 68 ioIn.seekg(-START_CODE_SIZE_FRAME, std::ios_base::cur); 69 temp -= (START_CODE_SIZE_FRAME - 1); 70 ret = false; 71 break; 72 } else if ((temp[START_CODE_OFFSET_ONE] == 0) && (temp[START_CODE_OFFSET_SEC] == 0)) { 73 ioIn.seekg(-START_CODE_SIZE_SLICE, std::ios_base::cur); 74 temp -= (START_CODE_SIZE_SLICE - 1); 75 ret = false; 76 break; 77 } 78 } 79 temp++; 80 } 81 filledCount = (temp - buf); 82 return ret; 83} 84 85CodecMpeg4Reader::CodecMpeg4Reader() : CodecPacketReader() 86{} 87 88bool CodecMpeg4Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 89{ 90 ioIn.read(buf, START_CODE_SIZE_SLICE); 91 if (ioIn.eof()) { 92 return true; 93 } 94 95 char *temp = buf; 96 temp += START_CODE_SIZE_SLICE; 97 bool ret = true; 98 bool findVop = false; 99 while (!ioIn.eof()) { 100 ioIn.read(temp, 1); 101 // check start code 102 if ((*temp == VOP_START) && (temp[START_CODE_OFFSET_ONE] == START_CODE) && (temp[START_CODE_OFFSET_SEC] == 0) && 103 (temp[START_CODE_OFFSET_THIRD] == 0)) { 104 findVop = true; 105 } 106 if (findVop && (*temp == START_CODE) && (temp[START_CODE_OFFSET_ONE] == 0) && 107 (temp[START_CODE_OFFSET_SEC] == 0)) { 108 temp -= START_CODE_SIZE_SLICE - 1; 109 ioIn.seekg(START_CODE_OFFSET_THIRD, std::ios_base::cur); 110 ret = false; 111 break; 112 } 113 temp++; 114 } 115 filledCount = (temp - buf); 116 return ret; 117} 118 119CodecVp9Reader::CodecVp9Reader() : CodecPacketReader() 120{} 121 122bool CodecVp9Reader::ReadOnePacket(std::ifstream &ioIn, char *buf, uint32_t &filledCount) 123{ 124 // vp9 saved in trunk, use ffmpeg to save vp9 to .vp9 file, the format like this: 125 // len(4 bytes, little-end, length of vp9 data) + vp9 data 126 filledCount = 0; 127 ioIn.read(reinterpret_cast<char *>(&filledCount), sizeof(filledCount)); 128 if (ioIn.eof()) { 129 return true; 130 } 131 filledCount = ntohl(filledCount); 132 ioIn.read(buf, filledCount); 133 if (ioIn.eof()) { 134 return true; 135 } 136 return false; 137}