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>
18 namespace {
19 constexpr int32_t START_CODE_OFFSET_ONE = -1;
20 constexpr int32_t START_CODE_OFFSET_SEC = -2;
21 constexpr int32_t START_CODE_OFFSET_THIRD = -3;
22 constexpr int32_t START_CODE_SIZE_FRAME = 4;
23 constexpr int32_t START_CODE_SIZE_SLICE = 3;
24 constexpr char START_CODE = 0x1;
25 constexpr char VOP_START = 0xB6;
26 } // namespace
27
GetPacketReader(const CodecMime & mime)28 CodecPacketReader::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
CodecH264Reader()48 CodecH264Reader::CodecH264Reader() : CodecPacketReader()
49 {}
50
ReadOnePacket(std::ifstream & ioIn,char * buf,uint32_t & filledCount)51 bool 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
CodecMpeg4Reader()85 CodecMpeg4Reader::CodecMpeg4Reader() : CodecPacketReader()
86 {}
87
ReadOnePacket(std::ifstream & ioIn,char * buf,uint32_t & filledCount)88 bool 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
CodecVp9Reader()119 CodecVp9Reader::CodecVp9Reader() : CodecPacketReader()
120 {}
121
ReadOnePacket(std::ifstream & ioIn,char * buf,uint32_t & filledCount)122 bool 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 }