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}