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
16#include "avmuxer_ffmpeg_demo.h"
17#include <dlfcn.h>
18#include <iostream>
19#include <fcntl.h>
20#include <fstream>
21#include "data_sink_fd.h"
22#include "plugin/plugin_manager_v2.h"
23
24namespace OHOS {
25namespace MediaAVCodec {
26int AVMuxerFFmpegDemo::DoAddTrack(int32_t &trackIndex, std::shared_ptr<Meta> trackDesc)
27{
28    int32_t tempTrackId = 0;
29    ffmpegMuxer_->AddTrack(tempTrackId, trackDesc);
30    if (tempTrackId < 0) {
31        std::cout<<"AVMuxerFFmpegDemo::DoAddTrack failed! trackId:"<<tempTrackId<<std::endl;
32        return -1;
33    }
34    trackIndex = tempTrackId;
35    return 0;
36}
37
38void AVMuxerFFmpegDemo::DoRunMuxer()
39{
40    long long testTimeStart = GetTimestamp();
41    std::string outFileName = GetOutputFileName("ffmpeg_mux");
42    outFd_ = open(outFileName.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
43    if (outFd_ < 0) {
44        std::cout<<"create muxer output file failed! fd:"<<outFd_<<std::endl;
45        return;
46    }
47    std::cout<<"==== open success! =====\noutputFileName: "<<outFileName<<"\n============"<<std::endl;
48
49    ffmpegMuxer_ = CreatePlugin(Plugins::OutputFormat::MPEG_4);
50    if (ffmpegMuxer_ == nullptr) {
51        std::cout<<"ffmpegMuxer create failed!"<<std::endl;
52        return;
53    }
54
55    ffmpegMuxer_->SetDataSink(std::make_shared<DataSinkFd>(outFd_));
56
57    AddAudioTrack(audioParams_);
58    AddVideoTrack(videoParams_);
59    AddCoverTrack(coverParams_);
60
61    ffmpegMuxer_->Start();
62    WriteCoverSample();
63    WriteTrackSample();
64    ffmpegMuxer_->Stop();
65    long long testTimeEnd = GetTimestamp();
66    std::cout << "muxer used time: " << testTimeEnd - testTimeStart << "us" << std::endl;
67}
68
69void AVMuxerFFmpegDemo::DoRunMultiThreadCase()
70{
71    std::cout<<"ffmpeg plugin demo is not support multi-thread write!"<<std::endl;
72    return;
73}
74
75int AVMuxerFFmpegDemo::DoWriteSample(uint32_t trackIndex, std::shared_ptr<AVBuffer> sample)
76{
77    if (ffmpegMuxer_ != nullptr &&
78        ffmpegMuxer_->WriteSample(trackIndex, sample) == Status::OK) {
79        return 0;
80    }
81    return -1;
82}
83
84std::shared_ptr<Plugins::MuxerPlugin> AVMuxerFFmpegDemo::CreatePlugin(Plugins::OutputFormat format)
85{
86    static const std::unordered_map<Plugins::OutputFormat, std::string> table = {
87        {Plugins::OutputFormat::DEFAULT, Plugins::MimeType::MEDIA_MP4},
88        {Plugins::OutputFormat::MPEG_4, Plugins::MimeType::MEDIA_MP4},
89        {Plugins::OutputFormat::M4A, Plugins::MimeType::MEDIA_M4A},
90        {Plugins::OutputFormat::MP3, Plugins::MimeType::MEDIA_MP3},
91    };
92
93    auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByMime(Plugins::PluginType::MUXER, table.at(format));
94    if (plugin == nullptr) {
95        return nullptr;
96    }
97    return std::reinterpret_pointer_cast<Plugins::MuxerPlugin>(plugin);
98}
99}  // namespace MediaAVCodec
100}  // namespace OHOS