1 /*
2 * Copyright (c) 2025 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 <fcntl.h>
17 #include <unistd.h>
18 #include <sys/stat.h>
19 #include <cstring>
20 #include <iostream>
21 #include <vector>
22 #include <memory>
23 #include <thread>
24 #include "demuxer_plugin_manager.h"
25 #include "stream_demuxer.h"
26 #include "common/media_source.h"
27 #include "plugin/plugin_manager_v2.h"
28 #include "buffer/avbuffer.h"
29 #include "demuxerplugintype_sample.h"
30
31 using namespace OHOS::Media;
32 using namespace OHOS::Media::Plugins;
33 using namespace OHOS::Media::Plugins::Ffmpeg;
34
35 namespace OHOS {
36 namespace Media {
37 constexpr uint32_t THREE = 3;
38 DemuxerPluginTypeTest::DemuxerPluginTypeTest() = default;
39
~DemuxerPluginTypeTest()40 DemuxerPluginTypeTest::~DemuxerPluginTypeTest()
41 {
42 if (fd_ >= 0) {
43 close(fd_);
44 }
45 fd_ = -1;
46 demuxerPlugin_ = nullptr;
47 }
48
InitWithData(const uint8_t * data,size_t size)49 bool DemuxerPluginTypeTest::InitWithData(const uint8_t* data, size_t size)
50 {
51 if (!data || size == 0) {
52 return false;
53 }
54 fd_ = open(testFilePath_, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
55 if (fd_ < 0) {
56 return false;
57 }
58 ssize_t len = write(fd_, data, size);
59 if (len != static_cast<ssize_t>(size)) {
60 close(fd_);
61 fd_ = -1;
62 return false;
63 }
64 lseek(fd_, 0, SEEK_SET);
65 dataSize_ = size;
66 return true;
67 }
68
PrepareDemuxerPlugin(MediaInfo & mediaInfo,size_t & bufferSize,AVBufferWrapper & buffer)69 void DemuxerPluginTypeTest::PrepareDemuxerPlugin(MediaInfo& mediaInfo, size_t& bufferSize, AVBufferWrapper& buffer)
70 {
71 std::string uri = "fd://" + std::to_string(fd_) + "?offset=0&size=" + std::to_string(dataSize_);
72 std::shared_ptr<MediaSource> mediaSource = std::make_shared<MediaSource>(uri);
73 std::shared_ptr<StreamDemuxer> streamDemuxer = std::make_shared<StreamDemuxer>();
74 std::shared_ptr<Source> source = std::make_shared<Source>();
75 source->SetSource(mediaSource);
76 streamDemuxer->SetSource(source);
77 streamDemuxer->SetSourceType(mediaSource->GetSourceType());
78 streamDemuxer->Init(uri);
79 streamDemuxer->SetDemuxerState(0, DemuxerState::DEMUXER_STATE_PARSE_FRAME);
80
81 dataSource = std::make_shared<DataSourceImpl>(streamDemuxer, 0);
82 auto basePlugin = PluginManagerV2::Instance().CreatePluginByName(demuxerPluginName_);
83 demuxerPlugin_ = std::reinterpret_pointer_cast<FFmpegDemuxerPlugin>(basePlugin);
84 if (!demuxerPlugin_) {
85 return;
86 }
87 if (demuxerPlugin_->SetDataSource(dataSource) != Status::OK) {
88 demuxerPlugin_ = nullptr;
89 return;
90 }
91
92 if (demuxerPlugin_->GetMediaInfo(mediaInfo) != Status::OK) {
93 demuxerPlugin_ = nullptr;
94 return;
95 }
96
97 int32_t width = videoWidthDefault_;
98 int32_t height = videoHeightDefault_;
99 for (const auto& track : mediaInfo.tracks) {
100 int32_t w = 0;
101 int32_t h = 0;
102 track.GetData(Tag::VIDEO_WIDTH, w);
103 track.GetData(Tag::VIDEO_HEIGHT, h);
104 if (w > 0 && h > 0) {
105 width = w;
106 height = h;
107 break;
108 }
109 }
110 bufferSize = width * height * 3; // 3 bytes per pixel (RGB)
111 buffer = AVBufferWrapper(bufferSize);
112 }
113
OperateDemuxerPlugin(MediaInfo & mediaInfo,size_t bufferSize,AVBufferWrapper & buffer)114 void DemuxerPluginTypeTest::OperateDemuxerPlugin(MediaInfo& mediaInfo, size_t bufferSize, AVBufferWrapper& buffer)
115 {
116 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
117 demuxerPlugin_->SelectTrack(idx);
118 }
119 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
120 demuxerPlugin_->UnselectTrack(idx);
121 }
122 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
123 demuxerPlugin_->SelectTrack(idx);
124 }
125
126 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
127 demuxerPlugin_->ReadSample(idx, buffer.mediaAVBuffer, interfaceTimeout_);
128 demuxerPlugin_->ReadSample(idx, buffer.mediaAVBuffer);
129 int32_t nextSampleSize = 0;
130 int64_t pts = 0;
131 demuxerPlugin_->GetNextSampleSize(idx, nextSampleSize, interfaceTimeout_);
132 demuxerPlugin_->GetLastPTSByTrackId(idx, pts);
133 demuxerPlugin_->Pause();
134 }
135
136 int64_t seekTime = 0;
137 demuxerPlugin_->SeekTo(-1, 0, SeekMode::SEEK_NEXT_SYNC, seekTime);
138 demuxerPlugin_->Flush();
139 demuxerPlugin_->SeekTo(0, seekTimeDefault_, SeekMode::SEEK_PREVIOUS_SYNC, seekTime);
140 demuxerPlugin_->Reset();
141 }
142
DemuxerPlugintask(MediaInfo & mediaInfo,AVBufferWrapper & buffer)143 void DemuxerPluginTypeTest::DemuxerPlugintask(MediaInfo& mediaInfo, AVBufferWrapper& buffer)
144 {
145 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
146 demuxerPlugin_->ReadSample(idx, buffer.mediaAVBuffer, interfaceTimeout_);
147 }
148 int64_t seekTime = 0;
149 demuxerPlugin_->SeekTo(0, seekTimeDefault_, SeekMode::SEEK_PREVIOUS_SYNC, seekTime);
150 }
151
RunDemuxerInterfaceFuzz()152 void DemuxerPluginTypeTest::RunDemuxerInterfaceFuzz()
153 {
154 if (fd_ < 0) {
155 return;
156 }
157 MediaInfo mediaInfo;
158 size_t bufferSize = 0;
159 AVBufferWrapper buffer(1); // 占位初始化
160 PrepareDemuxerPlugin(mediaInfo, bufferSize, buffer);
161 if (!demuxerPlugin_) {
162 return;
163 }
164 OperateDemuxerPlugin(mediaInfo, bufferSize, buffer);
165 if (demuxerPlugin_->SetDataSource(dataSource) != Status::OK) {
166 demuxerPlugin_ = nullptr;
167 return;
168 }
169 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
170 demuxerPlugin_->SelectTrack(idx);
171 }
172 std::thread readPluginThread1([mediaInfo, this]() {
173 MediaInfo Info = mediaInfo;
174 AVBufferWrapper buf(videoWidthDefault_ * videoHeightDefault_ * THREE);
175 DemuxerPlugintask(Info, buf);
176 });
177 std::thread readPluginThread2([mediaInfo, this]() {
178 MediaInfo Info1 = mediaInfo;
179 AVBufferWrapper buf1(videoWidthDefault_ * videoHeightDefault_ * THREE);
180 DemuxerPlugintask(Info1, buf1);
181 });
182 readPluginThread1.join();
183 readPluginThread2.join();
184 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
185 demuxerPlugin_->UnselectTrack(idx);
186 }
187 }
188
189 } // namespace Media
190 } // namespace OHOS