1 /*
2  * Copyright (c) 2023 Huawei Device 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 
16 #include "frame_detector.h"
17 
18 #include <algorithm>
19 #include <memory>
20 
21 namespace OHOS {
22 namespace Media {
23 using namespace std;
24 
GetFrameDetector(CodeType type)25 std::shared_ptr<FrameDetector> FrameDetector::GetFrameDetector(CodeType type)
26 {
27     switch (type) {
28         case CodeType::H264:
29             static std::shared_ptr<FrameDetectorH264> frameDetectorH264 = make_shared<FrameDetectorH264>();
30             return frameDetectorH264;
31         case CodeType::H265:
32             static std::shared_ptr<FrameDetectorH265> frameDetectorH265 = make_shared<FrameDetectorH265>();
33             return frameDetectorH265;
34         default:
35             return nullptr;
36     }
37 }
38 
IsContainIdrFrame(const uint8_t * buff,size_t bufSize)39 bool FrameDetector::IsContainIdrFrame(const uint8_t* buff, size_t bufSize)
40 {
41     if (buff == nullptr) {
42         return false;
43     }
44     using FirstByteInNalu = uint8_t;
45     list<pair<size_t, FirstByteInNalu>> posOfNalUnit;
46     size_t pos = 0;
47     while (pos < bufSize) {
48         auto pFound = search(buff + pos, buff + bufSize, begin(START_CODE), end(START_CODE));
49         pos = static_cast<size_t>(distance(buff, pFound));
50         if (pos == bufSize || pos + START_CODE_LEN >= bufSize) { // fail to find startCode or just at the end
51             break;
52         }
53         posOfNalUnit.emplace_back(pos, buff[pos + START_CODE_LEN]);
54         pos += START_CODE_LEN;
55     }
56     for (auto it = posOfNalUnit.begin(); it != posOfNalUnit.end(); ++it) {
57         auto nex = next(it);
58         NALUInfo nal {
59             .startPos = it->first,
60             .endPos = (nex == posOfNalUnit.end()) ? (bufSize) : (nex->first),
61             .nalType = GetNalType(it->second),
62         };
63         if (IsIDR(nal.nalType)) {
64             return true;
65         }
66     }
67     return false;
68 }
69 
GetNalType(uint8_t byte)70 uint8_t FrameDetectorH264::GetNalType(uint8_t byte)
71 {
72     return byte & 0b0001'1111;
73 }
74 
IsPPS(uint8_t nalType)75 bool FrameDetectorH264::IsPPS(uint8_t nalType)
76 {
77     return nalType == H264NalType::PPS;
78 }
79 
IsVCL(uint8_t nalType)80 bool FrameDetectorH264::IsVCL(uint8_t nalType)
81 {
82     return nalType >= H264NalType::NON_IDR && nalType <= H264NalType::IDR;
83 }
84 
IsIDR(uint8_t nalType)85 bool FrameDetectorH264::IsIDR(uint8_t nalType)
86 {
87     return nalType == H264NalType::IDR;
88 }
89 
GetNalType(uint8_t byte)90 uint8_t FrameDetectorH265::GetNalType(uint8_t byte)
91 {
92     return (byte & 0b0111'1110) >> 1;
93 }
94 
IsPPS(uint8_t nalType)95 bool FrameDetectorH265::IsPPS(uint8_t nalType)
96 {
97     return nalType == H265NalType::HEVC_PPS_NUT;
98 }
99 
IsVCL(uint8_t nalType)100 bool FrameDetectorH265::IsVCL(uint8_t nalType)
101 {
102     return nalType >= H265NalType::HEVC_TRAIL_N && nalType <= H265NalType::HEVC_CRA_NUT;
103 }
104 
IsIDR(uint8_t nalType)105 bool FrameDetectorH265::IsIDR(uint8_t nalType)
106 {
107     return nalType == H265NalType::HEVC_IDR_W_RADL ||
108            nalType == H265NalType::HEVC_IDR_N_LP ||
109            nalType == H265NalType::HEVC_CRA_NUT;
110 }
111 
IsPrefixSEI(uint8_t nalType)112 bool FrameDetectorH265::IsPrefixSEI(uint8_t nalType)
113 {
114     return nalType == H265NalType::HEVC_PREFIX_SEI_NUT;
115 }
116 } // namespace Media
117 } // namespace OHOS