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 "demuxer_plugin_manager.h"
24 #include "stream_demuxer.h"
25 #include "common/media_source.h"
26 #include "plugin/plugin_manager_v2.h"
27 #include "buffer/avbuffer.h"
28 #include "demuxerpluginflv_sample.h"
29
30 using namespace OHOS::Media;
31 using namespace OHOS::Media::Plugins;
32 using namespace OHOS::Media::Plugins::Ffmpeg;
33
34 namespace OHOS {
35 namespace Media {
36 const char* TEST_FILE_PATH = "/data/test/demuxerpluginflvfuzztest.flv";
37 const int32_t VIDEO_HEIGHT_DEFAULT = 1280;
38 const int32_t VIDEO_WIDTH_DEFAULT = 720;
39 const uint32_t INTERFACE_TIMEOUT = 100;
40 const int64_t SEEK_TIME_DEFAULT = 1000;
41
42 DemuxerPluginFlvTest::DemuxerPluginFlvTest() = default;
43
~DemuxerPluginFlvTest()44 DemuxerPluginFlvTest::~DemuxerPluginFlvTest()
45 {
46 if (fd_ >= 0) {
47 close(fd_);
48 }
49 fd_ = -1;
50 demuxerPlugin_ = nullptr;
51 }
52
InitWithFlvData(const uint8_t * data,size_t size)53 bool DemuxerPluginFlvTest::InitWithFlvData(const uint8_t* data, size_t size)
54 {
55 if (!data || size == 0) {
56 return false;
57 }
58 fd_ = open(TEST_FILE_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
59 if (fd_ < 0) {
60 return false;
61 }
62 ssize_t len = write(fd_, data, size);
63 if (len != static_cast<ssize_t>(size)) {
64 close(fd_);
65 fd_ = -1;
66 return false;
67 }
68 lseek(fd_, 0, SEEK_SET);
69 dataSize_ = size;
70 return true;
71 }
72
PrepareDemuxerPlugin(MediaInfo & mediaInfo,size_t & bufferSize,AVBufferWrapper & buffer)73 void DemuxerPluginFlvTest::PrepareDemuxerPlugin(MediaInfo& mediaInfo, size_t& bufferSize, AVBufferWrapper& buffer)
74 {
75 std::string uri = "fd://" + std::to_string(fd_) + "?offset=0&size=" + std::to_string(dataSize_);
76 std::shared_ptr<MediaSource> mediaSource = std::make_shared<MediaSource>(uri);
77 std::shared_ptr<StreamDemuxer> streamDemuxer = std::make_shared<StreamDemuxer>();
78 std::shared_ptr<Source> source = std::make_shared<Source>();
79 source->SetSource(mediaSource);
80 streamDemuxer->SetSource(source);
81 streamDemuxer->SetSourceType(mediaSource->GetSourceType());
82 streamDemuxer->Init(uri);
83 streamDemuxer->SetDemuxerState(0, DemuxerState::DEMUXER_STATE_PARSE_FRAME);
84
85 auto dataSource = std::make_shared<DataSourceImpl>(streamDemuxer, 0);
86 auto basePlugin = PluginManagerV2::Instance().CreatePluginByName("avdemux_flv");
87 demuxerPlugin_ = std::reinterpret_pointer_cast<FFmpegDemuxerPlugin>(basePlugin);
88 if (!demuxerPlugin_) {
89 return;
90 }
91 if (demuxerPlugin_->SetDataSource(dataSource) != Status::OK) {
92 demuxerPlugin_ = nullptr;
93 return;
94 }
95
96 if (demuxerPlugin_->GetMediaInfo(mediaInfo) != Status::OK) {
97 demuxerPlugin_ = nullptr;
98 return;
99 }
100
101 int32_t width = VIDEO_WIDTH_DEFAULT;
102 int32_t height = VIDEO_HEIGHT_DEFAULT;
103 for (const auto& track : mediaInfo.tracks) {
104 int32_t w = 0;
105 int32_t h = 0;
106 track.GetData(Tag::VIDEO_WIDTH, w);
107 track.GetData(Tag::VIDEO_HEIGHT, h);
108 if (w > 0 && h > 0) {
109 width = w;
110 height = h;
111 break;
112 }
113 }
114 bufferSize = width * height * 3; // 3 bytes per pixel (RGB)
115 buffer = AVBufferWrapper(bufferSize);
116 }
117
OperateDemuxerPlugin(MediaInfo & mediaInfo,size_t bufferSize,AVBufferWrapper & buffer)118 void DemuxerPluginFlvTest::OperateDemuxerPlugin(MediaInfo& mediaInfo, size_t bufferSize, AVBufferWrapper& buffer)
119 {
120 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
121 demuxerPlugin_->SelectTrack(idx);
122 }
123 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
124 demuxerPlugin_->UnselectTrack(idx);
125 }
126 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
127 demuxerPlugin_->SelectTrack(idx);
128 }
129 demuxerPlugin_->BoostReadThreadPriority();
130 for (uint32_t idx = 0; idx < mediaInfo.tracks.size(); ++idx) {
131 demuxerPlugin_->ReadSample(idx, buffer.mediaAVBuffer, INTERFACE_TIMEOUT);
132 demuxerPlugin_->ReadSample(idx, buffer.mediaAVBuffer);
133 int32_t nextSampleSize = 0;
134 int64_t pts = 0;
135 demuxerPlugin_->GetNextSampleSize(idx, nextSampleSize, INTERFACE_TIMEOUT);
136 demuxerPlugin_->GetLastPTSByTrackId(idx, pts);
137 demuxerPlugin_->Pause();
138 }
139
140 int64_t seekTime = 0;
141 demuxerPlugin_->SeekTo(-1, 0, SeekMode::SEEK_NEXT_SYNC, seekTime);
142 demuxerPlugin_->Flush();
143 demuxerPlugin_->SeekTo(0, SEEK_TIME_DEFAULT, SeekMode::SEEK_PREVIOUS_SYNC, seekTime);
144 demuxerPlugin_->Reset();
145 }
146
RunDemuxerInterfaceFuzz()147 void DemuxerPluginFlvTest::RunDemuxerInterfaceFuzz()
148 {
149 if (fd_ < 0) {
150 return;
151 }
152 MediaInfo mediaInfo;
153 size_t bufferSize = 0;
154 AVBufferWrapper buffer(1); // 占位初始化
155 PrepareDemuxerPlugin(mediaInfo, bufferSize, buffer);
156 if (!demuxerPlugin_) {
157 return;
158 }
159 OperateDemuxerPlugin(mediaInfo, bufferSize, buffer);
160 }
161
162 } // namespace Media
163 } // namespace OHOS