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