• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }