1 /*
2  * Copyright (C) 2024 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 <cinttypes>
17 #include <cstdio>
18 #include <fcntl.h>
19 #include <iostream>
20 #include <malloc.h>
21 #include <string>
22 #include <thread>
23 #include <sys/stat.h>
24 #include <fstream>
25 #include <ctime>
26 #include "native_avbuffer.h"
27 #include "inner_demuxer_parser_sample.h"
28 #include "native_avcodec_base.h"
29 #include "meta/format.h"
30 #include "avcodec_errors.h"
31 #include "avcodec_common.h"
32 #include "native_avformat.h"
33 #include "av_common.h"
34 #include "layer_info_all_i_avc.h"
35 #include "layer_info_all_i__hevc.h"
36 #include "layer_info_ipb_avc.h"
37 #include "layer_info_ipb_hevc.h"
38 #include "layer_info_one_i_avc.h"
39 #include "layer_info_one_i_hevc.h"
40 #include "layer_info_sdtp_avc.h"
41 #include "layer_info_sdtp_hevc.h"
42 #include "layer_info_four_layer_avc.h"
43 #include "layer_info_four_layer_hevc.h"
44 #include "layer_info_ltr_avc.h"
45 #include "layer_info_ltr_hevc.h"
46 #include "layer_info_three_layer_avc.h"
47 #include "layer_info_three_layer_hevc.h"
48 #include "layer_info_two_layer_avc.h"
49 #include "layer_info_two_layer_hevc.h"
50 #include "layer_info_sdtp_extended_hevc.h"
51 #include "layer_info_hdr_1_hevc.h"
52 #include "layer_info_hdr_2_hevc.h"
53 #include <random>
54 
55 using namespace std;
56 using namespace OHOS::MediaAVCodec;
57 using namespace OHOS::Media;
58 
59 using json = nlohmann::json;
60 
from_json(const nlohmann::json & j,JsonGopInfo & gop)61 void from_json(const nlohmann::json &j, JsonGopInfo &gop)
62 {
63     j.at("gopId").get_to(gop.gopId);
64     j.at("gopSize").get_to(gop.gopSize);
65     j.at("startFrameId").get_to(gop.startFrameId);
66 }
67 
from_json(const nlohmann::json & j,JsonFrameLayerInfo & frame)68 void from_json(const nlohmann::json &j, JsonFrameLayerInfo &frame)
69 {
70     j.at("frameId").get_to(frame.frameId);
71     j.at("dts").get_to(frame.dts);
72     j.at("layer").get_to(frame.layer);
73     j.at("discardable").get_to(frame.discardable);
74 }
75 
76 namespace OHOS {
77 namespace MediaAVCodec {
78 std::random_device rd;
InnerDemuxerParserSample(const std::string & filePath)79 InnerDemuxerParserSample::InnerDemuxerParserSample(const std::string &filePath)
80 {
81     fd = open(filePath.c_str(), O_RDONLY);
82     this->avsource_ = AVSourceFactory::CreateWithFD(fd, 0, GetFileSize(filePath));
83     if (!avsource_) {
84         printf("Source is null\n");
85         return;
86     }
87     this->demuxer_ = AVDemuxerFactory::CreateWithSource(avsource_);
88     if (!demuxer_) {
89         printf("AVDemuxerFactory::CreateWithSource is failed\n");
90         return;
91     }
92     int32_t ret = this->avsource_->GetSourceFormat(source_format_);
93     if (ret != 0) {
94         printf("GetSourceFormat is failed\n");
95     }
96     source_format_.GetIntValue(OH_MD_KEY_TRACK_COUNT, trackCount);
97     source_format_.GetLongValue(OH_MD_KEY_DURATION, duration);
98     printf("====>total tracks:%d duration:%" PRId64 "\n", trackCount, duration);
99     int32_t trackType = 0;
100     for (int32_t i = 0; i < trackCount; i++) {
101         ret = this->avsource_->GetTrackFormat(track_format_, i);
102         if (ret != 0) {
103             printf("GetTrackFormat is failed\n");
104         }
105         track_format_.GetIntValue(OH_MD_KEY_TRACK_TYPE, trackType);
106         if (trackType == MEDIA_TYPE_VID) {
107             ret = this->demuxer_->SelectTrackByID(i);
108             if (ret != 0) {
109                 printf("SelectTrackByID is failed\n");
110             }
111             videoTrackIdx = i;
112         }
113     }
114 }
115 
~InnerDemuxerParserSample()116 InnerDemuxerParserSample::~InnerDemuxerParserSample()
117 {
118     if (fd > 0) {
119         close(fd);
120         fd = 0;
121     }
122     if (avsource_ != nullptr) {
123         avsource_ = nullptr;
124     }
125     if (demuxer_ != nullptr) {
126         demuxer_ = nullptr;
127     }
128 }
129 
InitParameter(MP4Scene scene)130 void InnerDemuxerParserSample::InitParameter(MP4Scene scene)
131 {
132     InitMP4Scene(scene);
133     uint32_t buffersize = 1024 * 1024;
134     std::shared_ptr<AVAllocator> allocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
135     avBuffer = OHOS::Media::AVBuffer::CreateAVBuffer(allocator, buffersize);
136     gopVec_ = gopJson_.get<std::vector<JsonGopInfo>>();
137     frameVec_ = frameLayerJson_.get<std::vector<JsonFrameLayerInfo>>();
138     for (auto gop : gopVec_) {
139         int32_t frameId = gop.startFrameId;
140         uint32_t layerMax = 0;
141         std::map<uint8_t, uint32_t> layerNumFrame;
142         for (int32_t i = 0; i < gop.gopSize; i++) {
143             JsonFrameLayerInfo frame = frameVec_[frameId + i];
144             if (frame.layer > layerMax) {
145                 layerMax = frame.layer;
146             }
147             auto it = layerNumFrame.find(frame.layer);
148             if (it != layerNumFrame.end()) {
149                 layerNumFrame[frame.layer] = layerNumFrame[frame.layer] + 1;
150             } else {
151                 layerNumFrame.emplace(frame.layer, 1);
152             }
153             frameMap_.emplace(frame.dts, frame);
154         }
155         gop.layerCount = layerMax + 1;
156         gop.layerFrameNum = layerNumFrame;
157         frameGopMap_.emplace(gop.gopId, gop);
158     }
159 }
160 
InitMP4Scene(MP4Scene scene)161 void InnerDemuxerParserSample::InitMP4Scene(MP4Scene scene)
162 {
163     InitAVCScene(scene);
164     InitHEVCScene(scene);
165 }
166 
InitAVCScene(MP4Scene scene)167 void InnerDemuxerParserSample::InitAVCScene(MP4Scene scene)
168 {
169     switch (scene) {
170         case MP4Scene::ONE_I_FRAME_AVC:
171             gopJson_ = GopInfoOneIAvc;
172             frameLayerJson_ = FrameLayerInfoOneIAvc;
173             break;
174         case MP4Scene::ALL_I_FRAME_AVC:
175             gopJson_ = GopInfoAllIAvc;
176             frameLayerJson_ = FrameLayerInfoAllIAvc;
177             break;
178         case MP4Scene::IPB_FRAME_AVC:
179             gopJson_ = GopInfoIpbAvc;
180             frameLayerJson_ = FrameLayerInfoIpbAvc;
181             break;
182         case MP4Scene::SDTP_FRAME_AVC:
183             gopJson_ = GopInfoStdpAvc;
184             frameLayerJson_ = FrameLayerInfoStdpAvc;
185             break;
186         case MP4Scene::OPENGOP_FRAME_AVC:
187             break;
188         case MP4Scene::LTR_FRAME_AVC:
189             gopJson_ = GopInfoLTRAvc;
190             frameLayerJson_ = FrameLayerInfoLTRAvc;
191             break;
192         case MP4Scene::TWO_LAYER_FRAME_AVC:
193             gopJson_ = GopInfoTwoLayerAvc;
194             frameLayerJson_ = FrameLayerInfoTwoLayerAvc;
195             break;
196         case MP4Scene::THREE_LAYER_FRAME_AVC:
197             gopJson_ = GopInfoThreeLayerAvc;
198             frameLayerJson_ = FrameLayerInfoThreeLayerAvc;
199             break;
200         case MP4Scene::FOUR_LAYER_FRAME_AVC:
201             gopJson_ = GopInfoFourLayerAvc;
202             frameLayerJson_ = FrameLayerInfoFourLayerAvc;
203             break;
204         default:
205             break;
206     }
207 }
208 
InitHEVCScene(MP4Scene scene)209 void InnerDemuxerParserSample::InitHEVCScene(MP4Scene scene)
210 {
211     switch (scene) {
212         case MP4Scene::ONE_I_FRAME_HEVC:
213             gopJson_ = GopInfoOneIHevc;
214             frameLayerJson_ = FrameLayerInfoOneIHevc;
215             break;
216         case MP4Scene::ALL_I_FRAME_HEVC:
217             gopJson_ = GopInfoAllIHevc;
218             frameLayerJson_ = FrameLayerInfoAllIHevc;
219             break;
220         case MP4Scene::IPB_FRAME_HEVC:
221             gopJson_ = GopInfoIpbHevc;
222             frameLayerJson_ = FrameLayerInfoIpbHevc;
223             break;
224         case MP4Scene::SDTP_FRAME_HEVC:
225             gopJson_ = GopInfoStdpHevc;
226             frameLayerJson_ = FrameLayerInfoStdpHevc;
227             break;
228         case MP4Scene::LTR_FRAME_HEVC:
229             gopJson_ = GopInfoLTRHevc;
230             frameLayerJson_ = FrameLayerInfoLTRHevc;
231             break;
232         case MP4Scene::TWO_LAYER_FRAME_HEVC:
233             gopJson_ = GopInfoTwoLayerHevc;
234             frameLayerJson_ = FrameLayerInfoTwoLayerHevc;
235             break;
236         case MP4Scene::THREE_LAYER_FRAME_HEVC:
237             gopJson_ = GopInfoThreeLayerHevc;
238             frameLayerJson_ = FrameLayerInfoThreeLayerHevc;
239             break;
240         case MP4Scene::FOUR_LAYER_FRAME_HEVC:
241             gopJson_ = GopInfoFourLayerHevc;
242             frameLayerJson_ = FrameLayerInfoFourLayerHevc;
243             break;
244         case MP4Scene::SDTP_EXTENDED_HEVC:
245             gopJson_ = GopInfoStdpExtendedHevc;
246             frameLayerJson_ = FrameLayerInfoStdpExtendedHevc;
247             break;
248         case MP4Scene::HDR_1_HEVC:
249             gopJson_ = GopInfoHdr1Hevc;
250             frameLayerJson_ = FrameLayerInfoHdr1Hevc;
251             break;
252         case MP4Scene::HDR_2_HEVC:
253             gopJson_ = GopInfoHdr2Hevc;
254             frameLayerJson_ = FrameLayerInfoHdr2Hevc;
255             break;
256         default:
257             break;
258     }
259 }
260 
GetFileSize(const std::string & filePath)261 size_t InnerDemuxerParserSample::GetFileSize(const std::string& filePath)
262 {
263     size_t fileSize = 0;
264     if (!filePath.empty()) {
265         struct stat fileStatus {};
266         if (stat(filePath.c_str(), &fileStatus) == 0) {
267             fileSize = static_cast<size_t>(fileStatus.st_size);
268         }
269     }
270     return fileSize;
271 }
272 
RunSeekScene(WorkPts workPts)273 bool InnerDemuxerParserSample::RunSeekScene(WorkPts workPts)
274 {
275     int64_t pts = GetPtsFromWorkPts(workPts);
276     float durationNum = 0.0;
277     if (pts > duration / durationNum) {
278         cout << "pts > duration" << endl;
279         return true;
280     }
281     int32_t ret = 0;
282     ret = this->demuxer_->StartReferenceParser(pts);
283     cout << "StartReferenceParser pts:" << pts << endl;
284     if (ret != 0) {
285         cout << "StartReferenceParser fail ret:" << ret << endl;
286         return false;
287     }
288     bool checkResult = true;
289     ret = demuxer_->SeekToTime(pts, Media::SeekMode::SEEK_PREVIOUS_SYNC);
290     if (ret != 0) {
291         cout << "SeekToTime fail ret:" << ret << endl;
292         return false;
293     }
294     usleep(usleepTime);
295     FrameLayerInfo frameLayerInfo;
296     bool isEosFlag = true;
297     int32_t ptsNum = 1000;
298     while (isEosFlag) {
299         ret = this->demuxer_->ReadSampleBuffer(videoTrackIdx, avBuffer);
300         if (ret != 0) {
301             cout << "ReadSampleBuffer fail ret:" << ret << endl;
302             isEosFlag = false;
303             break;
304         }
305         if (avBuffer->pts_ >= pts * ptsNum || avBuffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
306             cout << "read sample end" << endl;
307             isEosFlag = false;
308             break;
309         }
310         this->demuxer_->GetFrameLayerInfo(avBuffer, frameLayerInfo);
311         cout << "isDiscardable: " << frameLayerInfo.isDiscardable << ", gopId: " << frameLayerInfo.gopId
312              << ", layer: " << frameLayerInfo.layer << ", dts_: " << avBuffer->dts_ << endl;
313         checkResult = CheckFrameLayerResult(frameLayerInfo, avBuffer->dts_, false);
314         if (!checkResult) {
315             cout << "CheckFrameLayerResult is false!!" << endl;
316             break;
317         }
318     }
319     return checkResult;
320 }
321 
RunSpeedScene(WorkPts workPts)322 bool InnerDemuxerParserSample::RunSpeedScene(WorkPts workPts)
323 {
324     int64_t pts = GetPtsFromWorkPts(workPts);
325     int32_t ret = 0;
326     ret = demuxer_->SeekToTime(pts, Media::SeekMode::SEEK_PREVIOUS_SYNC);
327     if (ret != 0) {
328         return false;
329     }
330     ret = this->demuxer_->StartReferenceParser(pts);
331     if (ret != 0) {
332         return false;
333     }
334     usleep(usleepTime);
335     FrameLayerInfo frameLayerInfo;
336     GopLayerInfo gopLayerInfo;
337     bool isEosFlag = true;
338     bool checkResult = true;
339     int num = 0;
340     while (isEosFlag) {
341         ret = this->demuxer_->ReadSampleBuffer(videoTrackIdx, avBuffer);
342         if (ret != 0) {
343             isEosFlag = false;
344             break;
345         }
346         if (avBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) {
347             isEosFlag = false;
348             break;
349         }
350         if (avBuffer->pts_ >= pts * num) {
351             ret = this->demuxer_->GetFrameLayerInfo(avBuffer, frameLayerInfo);
352             if (ret != 0) {
353                 checkResult = false;
354                 break;
355             }
356             checkResult = CheckFrameLayerResult(frameLayerInfo, avBuffer->dts_, true);
357             if (!checkResult) {
358                 break;
359             }
360             ret = this->demuxer_->GetGopLayerInfo(frameLayerInfo.gopId, gopLayerInfo);
361             if (ret != 0) {
362                 checkResult = false;
363                 break;
364             }
365             checkResult = CheckGopLayerResult(gopLayerInfo, frameLayerInfo.gopId);
366             if (!checkResult) {
367                 break;
368             }
369         }
370     }
371     return checkResult;
372 }
373 
CheckFrameLayerResult(FrameLayerInfo & info,int64_t dts,bool speedScene)374 bool InnerDemuxerParserSample::CheckFrameLayerResult(FrameLayerInfo &info, int64_t dts, bool speedScene)
375 {
376     JsonFrameLayerInfo frame = frameMap_[dts];
377     if ((frame.discardable && info.isDiscardable) || (!frame.discardable && !info.isDiscardable)) {
378         if (speedScene) {
379             if ((GetGopIdFromFrameId(frame.frameId) != info.gopId) || (frame.layer != info.layer)) {
380                 return false;
381             }
382         }
383         return true;
384     }
385     return false;
386 }
387 
CheckGopLayerResult(GopLayerInfo & info,int32_t gopId)388 bool InnerDemuxerParserSample::CheckGopLayerResult(GopLayerInfo &info, int32_t gopId)
389 {
390     JsonGopInfo frame = frameGopMap_[gopId];
391     bool conditionOne = (frame.gopSize != info.gopSize);
392     bool conditionTwo = (frame.layerCount != info.layerCount);
393     bool conditionThree = (!std::equal(frame.layerFrameNum.begin(),
394     frame.layerFrameNum.end(), info.layerFrameNum.begin()));
395     if (conditionOne || conditionTwo || conditionThree) {
396         return false;
397     }
398     return true;
399 }
400 
GetGopIdFromFrameId(int32_t frameId)401 uint32_t InnerDemuxerParserSample::GetGopIdFromFrameId(int32_t frameId)
402 {
403     uint32_t gopId = 0;
404     for (auto gop : gopVec_) {
405         if ((frameId >= gop.startFrameId) && (frameId < gop.startFrameId + gop.gopSize)) {
406             gopId = gop.gopId;
407             break;
408         }
409     }
410     return gopId;
411 }
412 
GetPtsFromWorkPts(WorkPts workPts)413 int64_t InnerDemuxerParserSample::GetPtsFromWorkPts(WorkPts workPts)
414 {
415     int64_t pts = 0;
416     float num = 1000.0;
417     switch (workPts) {
418         case WorkPts::START_PTS:
419             pts = 0;
420             break;
421         case WorkPts::END_PTS:
422             pts = duration / num;
423             break;
424         case WorkPts::RANDOM_PTS:
425             srand(time(NULL));
426             pts = rd() % duration / num;
427             break;
428         case WorkPts::SPECIFIED_PTS:
429             pts = specified_pts;
430             break;
431         default:
432             break;
433     }
434     cout << "GetPtsFromWorkPts pts:" << pts << endl;
435     return pts;
436 }
437 }
438 }