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 #include "demuxer_sample.h"
16 #include <cstddef>
17 #include <cstdint>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/stat.h>
21 #include <iostream>
22
23 using namespace OHOS;
24 using namespace OHOS::Media;
25 using namespace std;
26
~DemuxerSample()27 DemuxerSample::~DemuxerSample()
28 {
29 if (fd > 0) {
30 close(fd);
31 fd = 0;
32 }
33 if (source != nullptr) {
34 OH_AVSource_Destroy(source);
35 source = nullptr;
36 }
37 if (uriSource != nullptr) {
38 OH_AVSource_Destroy(uriSource);
39 uriSource = nullptr;
40 }
41 if (demuxer != nullptr) {
42 OH_AVDemuxer_Destroy(demuxer);
43 demuxer = nullptr;
44 }
45 if (sourceFormat != nullptr) {
46 OH_AVFormat_Destroy(sourceFormat);
47 sourceFormat = nullptr;
48 }
49 if (memory != nullptr) {
50 OH_AVMemory_Destroy(memory);
51 memory = nullptr;
52 }
53 if (buffer != nullptr) {
54 OH_AVBuffer_Destroy(buffer);
55 buffer = nullptr;
56 }
57 if (format != nullptr) {
58 OH_AVFormat_Destroy(format);
59 format = nullptr;
60 }
61 if (audioFormat != nullptr) {
62 OH_AVFormat_Destroy(audioFormat);
63 audioFormat = nullptr;
64 }
65 if (videoFormat != nullptr) {
66 OH_AVFormat_Destroy(videoFormat);
67 videoFormat = nullptr;
68 }
69 }
70
GetFileSize(const char * fileName)71 static int64_t GetFileSize(const char *fileName)
72 {
73 int64_t fileSize = 0;
74 if (fileName != nullptr) {
75 struct stat fileStatus {};
76 if (stat(fileName, &fileStatus) == 0) {
77 fileSize = static_cast<int64_t>(fileStatus.st_size);
78 }
79 }
80 return fileSize;
81 }
82
CreateDemuxer()83 int DemuxerSample::CreateDemuxer()
84 {
85 fd = open(filePath, O_RDONLY);
86 int64_t size = GetFileSize(filePath);
87 source = OH_AVSource_CreateWithFD(fd, 0, size);
88 if (!source) {
89 close(fd);
90 fd = 0;
91 return -1;
92 }
93 demuxer = OH_AVDemuxer_CreateWithSource(source);
94 if (!demuxer) {
95 OH_AVSource_Destroy(source);
96 source = nullptr;
97 close(fd);
98 fd = 0;
99 return -1;
100 }
101 return 0;
102 }
103
GetAndSetFormat(const char * setLanguage,Params params)104 void DemuxerSample::GetAndSetFormat(const char *setLanguage, Params params)
105 {
106 int64_t duration = 0;
107 OH_AVFormat_GetLongValue(sourceFormat, OH_MD_KEY_DURATION, &duration);
108 float currentHeight = 0;
109 OH_AVFormat_GetFloatValue(sourceFormat, OH_MD_KEY_HEIGHT, ¤tHeight);
110 double frameRate;
111 OH_AVFormat_GetDoubleValue(sourceFormat, OH_MD_KEY_FRAME_RATE, &frameRate);
112 const char* language = nullptr;
113 OH_AVFormat_GetStringValue(sourceFormat, OH_MD_KEY_LANGUAGE, &language);
114 uint8_t *codecConfig = nullptr;
115 size_t bufferSize;
116 OH_AVFormat_GetBuffer(sourceFormat, OH_MD_KEY_CODEC_CONFIG, &codecConfig, &bufferSize);
117 language = OH_AVFormat_DumpInfo(sourceFormat);
118 format = OH_AVFormat_Create();
119 OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRACK_TYPE, params.setTrackType);
120 OH_AVFormat_SetLongValue(format, OH_MD_KEY_DURATION, params.setDuration);
121 OH_AVFormat_SetFloatValue(format, OH_MD_KEY_HEIGHT, params.setHeight);
122 OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, params.setFrameRate);
123 OH_AVFormat_SetStringValue(format, OH_MD_KEY_LANGUAGE, setLanguage);
124 char configBuffer[params.setCodecConfigSize];
125 OH_AVFormat_SetBuffer(format, OH_MD_KEY_CODEC_CONFIG, (uint8_t *)configBuffer, params.setCodecConfigSize);
126 OH_AVFormat_Copy(format, sourceFormat);
127 audioFormat = OH_AVFormat_CreateAudioFormat(OH_AVCODEC_MIMETYPE_AUDIO_AAC, params.sampleRate, params.channelCount);
128 videoFormat = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC,
129 params.setVideoWidth, params.setVideoHeight);
130 }
131
RunNormalDemuxer(uint32_t createSize,const char * uri,const char * setLanguage,Params params)132 void DemuxerSample::RunNormalDemuxer(uint32_t createSize, const char *uri, const char *setLanguage, Params params)
133 {
134 gReadEnd = false;
135 int ret = CreateDemuxer();
136 if (ret < 0) {
137 return;
138 }
139 sourceFormat = OH_AVSource_GetSourceFormat(source);
140 if (sourceFormat == nullptr) {
141 return;
142 }
143 OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &gTrackCount);
144 for (int32_t index = 0; index < gTrackCount; index++) {
145 OH_AVDemuxer_SelectTrackByID(demuxer, index);
146 }
147 memory = OH_AVMemory_Create(createSize);
148 while (!gReadEnd && gTrackCount > 0) {
149 for (int32_t index = 0; index < gTrackCount; index++) {
150 OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
151 if (trackFormat == nullptr) {
152 gReadEnd = true;
153 break;
154 }
155 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &gTrackType);
156 if (trackFormat) {
157 OH_AVFormat_Destroy(trackFormat);
158 trackFormat = nullptr;
159 }
160 ret = OH_AVDemuxer_ReadSample(demuxer, index, memory, &attr);
161 if (ret != 0) {
162 gReadEnd = true;
163 break;
164 }
165 if (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
166 gReadEnd = true;
167 break;
168 }
169 }
170 }
171 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_CLOSEST_SYNC);
172 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_PREVIOUS_SYNC);
173 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_NEXT_SYNC);
174 for (int32_t index = 0; index < gTrackCount; index++) {
175 OH_AVDemuxer_UnselectTrackByID(demuxer, index);
176 }
177 GetAndSetFormat(setLanguage, params);
178 uriSource = OH_AVSource_CreateWithURI(const_cast<char *>(uri));
179 }
180
RunNormalDemuxerApi11(uint32_t createSize,const char * uri,const char * setLanguage,Params params)181 void DemuxerSample::RunNormalDemuxerApi11(uint32_t createSize, const char *uri, const char *setLanguage, Params params)
182 {
183 gReadEnd = false;
184 int ret = CreateDemuxer();
185 if (ret < 0) {
186 return;
187 }
188 sourceFormat = OH_AVSource_GetSourceFormat(source);
189 if (sourceFormat == nullptr) {
190 return;
191 }
192 OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &gTrackCount);
193 for (int32_t index = 0; index < gTrackCount; index++) {
194 OH_AVDemuxer_SelectTrackByID(demuxer, index);
195 }
196 buffer = OH_AVBuffer_Create(createSize);
197 while (!gReadEnd && gTrackCount > 0) {
198 for (int32_t index = 0; index < gTrackCount; index++) {
199 OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
200 if (trackFormat == nullptr) {
201 gReadEnd = true;
202 break;
203 }
204 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &gTrackType);
205 if (trackFormat) {
206 OH_AVFormat_Destroy(trackFormat);
207 trackFormat = nullptr;
208 }
209 ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, index, buffer);
210 if (ret != 0) {
211 gReadEnd = true;
212 break;
213 }
214 OH_AVBuffer_GetBufferAttr(buffer, &attr);
215 if (attr.flags & OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
216 gReadEnd = true;
217 break;
218 }
219 }
220 }
221 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_CLOSEST_SYNC);
222 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_PREVIOUS_SYNC);
223 OH_AVDemuxer_SeekToTime(demuxer, params.time, SEEK_MODE_NEXT_SYNC);
224 for (int32_t index = 0; index < gTrackCount; index++) {
225 OH_AVDemuxer_UnselectTrackByID(demuxer, index);
226 }
227 GetAndSetFormat(setLanguage, params);
228 uriSource = OH_AVSource_CreateWithURI(const_cast<char *>(uri));
229 }