• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "avmuxer_demo_base.h"
16 #include <unistd.h>
17 #include <iostream>
18 #include <fstream>
19 #include "avcodec_errors.h"
20 #include "avcodec_common.h"
21 
22 namespace {
23     constexpr int MODE_ZERO = 0;
24     constexpr int MODE_ONE = 1;
25     constexpr int MODE_TWO = 2;
26     constexpr int MODE_THREE = 3;
27     constexpr int CONFIG_BUFFER_SZIE = 0x1FFF;
28 }
29 
30 namespace OHOS {
31 namespace MediaAVCodec {
32 const AudioTrackParam *AVMuxerDemoBase::audioParams_ = nullptr;
33 const VideoTrackParam *AVMuxerDemoBase::videoParams_ = nullptr;
34 const VideoTrackParam *AVMuxerDemoBase::coverParams_ = nullptr;
35 std::string AVMuxerDemoBase::videoType_ = std::string("");
36 std::string AVMuxerDemoBase::audioType_ = std::string("");
37 std::string AVMuxerDemoBase::coverType_ = std::string("");
38 std::string AVMuxerDemoBase::format_ = std::string("");
39 OutputFormat AVMuxerDemoBase::outputFormat_ = OUTPUT_FORMAT_DEFAULT;
40 bool AVMuxerDemoBase::hasSetMode_ = false;
41 
AVMuxerDemoBase()42 AVMuxerDemoBase::AVMuxerDemoBase()
43 {
44 }
45 
OpenFile(const std::string & filePath)46 std::shared_ptr<std::ifstream> OpenFile(const std::string &filePath)
47 {
48     auto file = std::make_shared<std::ifstream>();
49     file->open(filePath, std::ios::in | std::ios::binary);
50     if (file->is_open()) {
51         return file;
52     }
53 
54     return nullptr;
55 }
56 
SelectFormatMode()57 void AVMuxerDemoBase::SelectFormatMode()
58 {
59     int num;
60     std::cout<<"\nplease select muxer type: 0.mp4 1.m4a"<<std::endl;
61     std::cin>>num;
62     switch (num) {
63         case MODE_ZERO:
64             format_ = "mp4";
65             outputFormat_ = OUTPUT_FORMAT_MPEG_4;
66             break;
67         case MODE_ONE:
68             format_ = "m4a";
69             outputFormat_ = OUTPUT_FORMAT_M4A;
70             break;
71         default:
72             format_ = "mp4";
73             outputFormat_ = OUTPUT_FORMAT_MPEG_4;
74             break;
75     }
76 }
77 
SelectAudioVideoMode()78 void AVMuxerDemoBase::SelectAudioVideoMode()
79 {
80     int num;
81     std::cout<<"\nplease select audio file: 0.noAudio 1.aac 2.mpeg"<<std::endl;
82     std::cin>>num;
83     switch (num) {
84         case MODE_ZERO:
85             audioType_ = "noAudio";
86             audioParams_ = nullptr;
87             break;
88         case MODE_ONE:
89             audioType_ = "aac";
90             audioParams_ = &g_audioAacPar;
91             break;
92         case MODE_TWO:
93             audioType_ = "mpeg";
94             audioParams_ = &g_audioMpegPar;
95             break;
96         default:
97             videoType_ = "noAudio";
98             audioParams_ = nullptr;
99             std::cout<<"do not support audio type index: "<<num<<", set to noAudio"<<std::endl;
100             break;
101     }
102 
103     std::cout<<"please select video file:0.noVideo 1.h264 2.mpeg4 3.h265"<<std::endl;
104     std::cin>>num;
105     switch (num) {
106         case MODE_ZERO:
107             videoType_ = "noVideo";
108             videoParams_ = nullptr;
109             break;
110         case MODE_ONE:
111             videoType_ = "h264";
112             videoParams_ = &g_videoH264Par;
113             break;
114         case MODE_TWO:
115             videoType_ = "mpeg4";
116             videoParams_ = &g_videoMpeg4Par;
117             break;
118         case MODE_THREE:
119             videoType_ = "h265";
120             videoParams_ = &g_videoH265Par;
121             break;
122         default:
123             videoType_ = "noVideo";
124             videoParams_ = nullptr;
125             std::cout<<"do not support video type index: "<<", set to noVideo"<<num<<std::endl;
126             break;
127     }
128 }
129 
SelectCoverMode()130 void AVMuxerDemoBase::SelectCoverMode()
131 {
132     int num;
133     std::cout<<"please select cover file:0.NoCover 1.jpg 2.png 3.bmp"<<std::endl;
134     std::cin>>num;
135     switch (num) {
136         case MODE_ZERO:
137             coverType_ = "noCover";
138             coverParams_ = nullptr;
139             break;
140         case MODE_ONE:
141             coverType_ = "jpg";
142             coverParams_ = &g_jpegCoverPar;
143             break;
144         case MODE_TWO:
145             coverType_ = "png";
146             coverParams_ = &g_pngCoverPar;
147             break;
148         case MODE_THREE:
149             coverType_ = "bmp";
150             coverParams_ = &g_bmpCoverPar;
151             break;
152         default:
153             coverType_ = "noCover";
154             coverParams_ = nullptr;
155             std::cout<<"do not support cover type index: "<<", set to noCover"<<num<<std::endl;
156             break;
157     }
158 }
159 
SelectMode()160 int AVMuxerDemoBase::SelectMode()
161 {
162     if (hasSetMode_) {
163         return 0;
164     }
165     SelectFormatMode();
166     SelectAudioVideoMode();
167     SelectCoverMode();
168 
169     hasSetMode_ = true;
170     return 0;
171 }
172 
SelectModeAndOpenFile()173 int AVMuxerDemoBase::SelectModeAndOpenFile()
174 {
175     if (SelectMode() != 0) {
176         return -1;
177     }
178 
179     if (audioParams_ != nullptr) {
180         audioFile_ = OpenFile(audioParams_->fileName);
181         if (audioFile_ == nullptr) {
182             std::cout<<"open audio file failed! file name:"<<audioParams_->fileName<<std::endl;
183             return -1;
184         }
185         std::cout<<"open audio file success! file name:"<<audioParams_->fileName<<std::endl;
186     }
187 
188     if (videoParams_ != nullptr) {
189         videoFile_ = OpenFile(videoParams_->fileName);
190         if (videoFile_ == nullptr) {
191             std::cout<<"open video file failed! file name:"<<videoParams_->fileName<<std::endl;
192             Reset();
193             return -1;
194         }
195         std::cout<<"video file success! file name:"<<videoParams_->fileName<<std::endl;
196     }
197 
198     if (coverParams_ != nullptr) {
199         coverFile_ = OpenFile(coverParams_->fileName);
200         if (coverFile_ == nullptr) {
201             std::cout<<"open cover file failed! file name:"<<coverParams_->fileName<<std::endl;
202             Reset();
203             return -1;
204         }
205         std::cout<<"cover file success! file name:"<<coverParams_->fileName<<std::endl;
206     }
207     return 0;
208 }
209 
Reset()210 void AVMuxerDemoBase::Reset()
211 {
212     if (outFd_ > 0) {
213         close(outFd_);
214         outFd_ = -1;
215     }
216     if (audioFile_ != nullptr) {
217         audioFile_->close();
218         audioFile_ = nullptr;
219     }
220     if (videoFile_ != nullptr) {
221         videoFile_->close();
222         videoFile_ = nullptr;
223     }
224     if (coverFile_ != nullptr) {
225         coverFile_->close();
226         coverFile_ = nullptr;
227     }
228 }
229 
RunCase()230 void AVMuxerDemoBase::RunCase()
231 {
232     if (SelectModeAndOpenFile() != 0) {
233         return;
234     }
235 
236     DoRunMuxer();
237 
238     Reset();
239 }
240 
RunMultiThreadCase()241 void AVMuxerDemoBase::RunMultiThreadCase()
242 {
243     std::cout<<"==== start AVMuxerDemoBase::RunMultiThreadCase ==="<<std::endl;
244     if (SelectModeAndOpenFile() != 0) {
245         return;
246     }
247 
248     DoRunMultiThreadCase();
249 
250     Reset();
251 }
252 
WriteSingleTrackSample(uint32_t trackId,std::shared_ptr<std::ifstream> file)253 void AVMuxerDemoBase::WriteSingleTrackSample(uint32_t trackId, std::shared_ptr<std::ifstream> file)
254 {
255     if (file == nullptr) {
256         std::cout<<"AVMuxerDemoBase::WriteTrackSample file is nullptr"<<std::endl;
257         return;
258     }
259     std::shared_ptr<AVSharedMemoryBase> buffer = nullptr;
260     AVCodecBufferInfo info {0, 0, 0};
261     AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
262     bool ret = ReadSampleDataInfo(file, buffer, info, flag);
263     while (ret) {
264         if (DoWriteSample(trackId, buffer, info, flag) != AVCS_ERR_OK) {
265             std::cout<<"WriteSample failed"<<std::endl;
266             break;
267         }
268         ret = ReadSampleDataInfo(file, buffer, info, flag);
269     }
270 }
271 
ReadSampleDataInfo(std::shared_ptr<std::ifstream> file,std::shared_ptr<AVSharedMemoryBase> & buffer,AVCodecBufferInfo & info,AVCodecBufferFlag & flag)272 bool AVMuxerDemoBase::ReadSampleDataInfo(std::shared_ptr<std::ifstream> file,
273                                          std::shared_ptr<AVSharedMemoryBase> &buffer,
274                                          AVCodecBufferInfo &info,
275                                          AVCodecBufferFlag &flag)
276 {
277     if (file->eof()) {
278         return false;
279     }
280     file->read(reinterpret_cast<char*>(&info.presentationTimeUs), sizeof(info.presentationTimeUs));
281 
282     if (file->eof()) {
283         return false;
284     }
285     file->read(reinterpret_cast<char*>(&flag), sizeof(flag));
286     if (flag & 0x01) {
287         flag = AVCODEC_BUFFER_FLAG_SYNC_FRAME;
288     }
289 
290     if (file->eof()) {
291         return false;
292     }
293     file->read(reinterpret_cast<char*>(&info.size), sizeof(info.size));
294 
295     if (file->eof()) {
296         return false;
297     }
298     if (buffer == nullptr || buffer->GetSize() < info.size) {
299         buffer = std::make_shared<AVSharedMemoryBase>(info.size, AVSharedMemory::FLAGS_READ_ONLY, "sampleData");
300         buffer->Init();
301     }
302     file->read(reinterpret_cast<char*>(buffer->GetBase()), info.size);
303     return true;
304 }
305 
WriteAvTrackSample()306 void AVMuxerDemoBase::WriteAvTrackSample()
307 {
308     if (audioFile_ == nullptr || videoFile_ == nullptr) {
309         return;
310     }
311     AVCodecBufferInfo audioInfo {0, 0, 0};
312     AVCodecBufferInfo videoInfo {0, 0, 0};
313     AVCodecBufferFlag audioFlag = AVCODEC_BUFFER_FLAG_NONE;
314     AVCodecBufferFlag videoFlag = AVCODEC_BUFFER_FLAG_NONE;
315     std::shared_ptr<AVSharedMemoryBase> audioBuffer = nullptr;
316     std::shared_ptr<AVSharedMemoryBase> videoBuffer = nullptr;
317     bool audioRet = ReadSampleDataInfo(audioFile_, audioBuffer, audioInfo, audioFlag);
318     bool videoRet = ReadSampleDataInfo(videoFile_, videoBuffer, videoInfo, videoFlag);
319     bool isOver = false;
320     while (!isOver && (audioRet || videoRet)) {
321         int ret = AVCS_ERR_OK;
322         if (audioRet && videoRet && audioInfo.presentationTimeUs <= videoInfo.presentationTimeUs) {
323             ret = DoWriteSample(audioTrackId_, audioBuffer, audioInfo, audioFlag);
324             audioRet = ReadSampleDataInfo(audioFile_, audioBuffer, audioInfo, audioFlag);
325         } else if (audioRet && videoRet) {
326             ret = DoWriteSample(videoTrackId_, videoBuffer, videoInfo, videoFlag);
327             videoRet = ReadSampleDataInfo(videoFile_, videoBuffer, videoInfo, videoFlag);
328         } else if (audioRet) {
329             ret = DoWriteSample(audioTrackId_, audioBuffer, audioInfo, audioFlag);
330             isOver = true;
331         } else {
332             ret = DoWriteSample(videoTrackId_, videoBuffer, videoInfo, videoFlag);
333             isOver = true;
334         }
335         if (ret != AVCS_ERR_OK) {
336             std::cout<<"WriteSample failed"<<std::endl;
337             break;
338         }
339     }
340 }
341 
WriteTrackSample()342 void AVMuxerDemoBase::WriteTrackSample()
343 {
344     if (audioFile_ != nullptr && videoFile_ != nullptr && audioTrackId_ >= 0 && videoTrackId_ >= 0) {
345         std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO and VIDEO sample"<<std::endl;
346         std::cout<<"audio trackId:"<<audioTrackId_<<" video trackId:"<<videoTrackId_<<std::endl;
347         WriteAvTrackSample();
348     } else if (audioFile_ != nullptr && audioTrackId_ >= 0) {
349         std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO sample"<<std::endl;
350         WriteSingleTrackSample(audioTrackId_, audioFile_);
351     } else if (videoFile_ != nullptr && videoTrackId_ >= 0) {
352         std::cout<<"AVMuxerDemoBase::WriteTrackSample write VIDEO sample"<<std::endl;
353         WriteSingleTrackSample(videoTrackId_, videoFile_);
354     } else {
355         std::cout<<"AVMuxerDemoBase::WriteTrackSample don't write AUDIO and VIDEO track!!"<<std::endl;
356     }
357 }
358 
MulThdWriteTrackSample(AVMuxerDemoBase * muxerBase,uint32_t trackId,std::shared_ptr<std::ifstream> file)359 void AVMuxerDemoBase::MulThdWriteTrackSample(AVMuxerDemoBase *muxerBase, uint32_t trackId,
360     std::shared_ptr<std::ifstream> file)
361 {
362     muxerBase->WriteSingleTrackSample(trackId, file);
363 }
364 
WriteCoverSample()365 void AVMuxerDemoBase::WriteCoverSample()
366 {
367     if (coverParams_ == nullptr) {
368         return;
369     }
370     std::cout<<"AVMuxerDemoBase::WriteCoverSample"<<std::endl;
371     if (coverFile_ == nullptr) {
372         std::cout<<"AVMuxerDemoBase::WriteCoverSample coverFile_ is nullptr!"<<std::endl;
373         return;
374     }
375     AVCodecBufferInfo info {0, 0, 0};
376     coverFile_->seekg(0, std::ios::end);
377     info.size = coverFile_->tellg();
378     coverFile_->seekg(0, std::ios::beg);
379     if (info.size <= 0) {
380         std::cout<<"AVMuxerDemoBase::WriteCoverSample coverFile_ size is 0!"<<std::endl;
381         return;
382     }
383 
384     std::shared_ptr<AVSharedMemoryBase> avMemBuffer =
385         std::make_shared<AVSharedMemoryBase>(info.size, AVSharedMemory::FLAGS_READ_ONLY, "sampleData");
386     avMemBuffer->Init();
387     coverFile_->read(reinterpret_cast<char*>(avMemBuffer->GetBase()), info.size);
388     if (DoWriteSample(coverTrackId_, avMemBuffer, info, AVCODEC_BUFFER_FLAG_NONE) != AVCS_ERR_OK) {
389         std::cout<<"WriteCoverSample error"<<std::endl;
390     }
391 }
392 
AddVideoTrack(const VideoTrackParam * param)393 int AVMuxerDemoBase::AddVideoTrack(const VideoTrackParam *param)
394 {
395     if (param == nullptr) {
396         std::cout<<"AVMuxerDemoBase::AddVideoTrack video is not select!"<<std::endl;
397         return -1;
398     }
399     MediaDescription videoParams;
400     videoParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
401     videoParams.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, param->width);
402     videoParams.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, param->height);
403     videoParams.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, param->frameRate);
404     videoParams.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_DELAY, param->videoDelay);
405 
406     int extSize = 0;
407     char buffer[CONFIG_BUFFER_SZIE] {0};
408     videoFile_->read(reinterpret_cast<char*>(&extSize), sizeof(extSize));
409     if (extSize > 0 && extSize < CONFIG_BUFFER_SZIE) {
410         videoFile_->read(reinterpret_cast<char*>(buffer), extSize);
411         videoParams.PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, reinterpret_cast<uint8_t*>(buffer), extSize);
412     } else {
413         std::cout<<"AVMuxerDemoBase::AddVideoTrack DoAddTrack failed!"<<std::endl;
414     }
415 
416     if (DoAddTrack(videoTrackId_, videoParams) != AVCS_ERR_OK) {
417         return -1;
418     }
419     std::cout << "AVMuxerDemoBase::AddVideoTrack video trackId is: " << videoTrackId_ << std::endl;
420     return 0;
421 }
422 
AddAudioTrack(const AudioTrackParam * param)423 int AVMuxerDemoBase::AddAudioTrack(const AudioTrackParam *param)
424 {
425     if (param == nullptr) {
426         std::cout<<"AVMuxerDemoBase::AddAudioTrack audio is not select!"<<std::endl;
427         return -1;
428     }
429     MediaDescription audioParams;
430     audioParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
431     audioParams.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, param->sampleRate);
432     audioParams.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, param->channels);
433     audioParams.PutIntValue(MediaDescriptionKey::MD_KEY_AUDIO_SAMPLES_PER_FRAME, param->frameSize);
434 
435     int extSize = 0;
436     char buffer[CONFIG_BUFFER_SZIE] {0};
437     audioFile_->read(reinterpret_cast<char*>(&extSize), sizeof(extSize));
438     if (extSize > 0 && extSize < CONFIG_BUFFER_SZIE) {
439         audioFile_->read(reinterpret_cast<char*>(buffer), extSize);
440         audioParams.PutBuffer(MediaDescriptionKey::MD_KEY_CODEC_CONFIG, reinterpret_cast<uint8_t*>(buffer), extSize);
441     } else {
442         std::cout<<"AVMuxerDemoBase::AddAudioTrack error extSize:"<<extSize<<std::endl;
443     }
444 
445     if (DoAddTrack(audioTrackId_, audioParams) != 0) {
446         std::cout<<"AVMuxerDemoBase::AddAudioTrack DoAddTrack failed!"<<std::endl;
447         return -1;
448     }
449     std::cout << "AVMuxerDemoBase::AddAudioTrack audio trackId is: " << audioTrackId_ << std::endl;
450     return 0;
451 }
452 
AddCoverTrack(const VideoTrackParam * param)453 int AVMuxerDemoBase::AddCoverTrack(const VideoTrackParam *param)
454 {
455     if (param == nullptr) {
456         std::cout<<"AVMuxerDemoBase::AddCoverTrack cover is not select!"<<std::endl;
457         return -1;
458     }
459     MediaDescription coverParams;
460     coverParams.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, param->mimeType);
461     coverParams.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, param->width);
462     coverParams.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, param->height);
463 
464     if (DoAddTrack(coverTrackId_, coverParams) != AVCS_ERR_OK) {
465         return -1;
466     }
467     std::cout << "AVMuxerDemoBase::AddCoverTrack video trackId is: " << coverTrackId_ << std::endl;
468     return 0;
469 }
470 } // MediaAVCodec
471 } // OHOS