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_engine_demo.h"
17#include <iostream>
18#include <fstream>
19#include <cstdio>
20#include <unistd.h>
21#include <fcntl.h>
22#include <thread>
23#include <vector>
24
25namespace OHOS {
26namespace MediaAVCodec {
27int AVMuxerEngineDemo::DoWriteSample(uint32_t trackIndex, std::shared_ptr<AVBuffer> sample)
28{
29    if (avmuxer_ != nullptr &&
30        avmuxer_->WriteSample(trackIndex, sample) == Status::OK) {
31            return 0;
32    }
33    return -1;
34}
35
36int AVMuxerEngineDemo::DoAddTrack(int32_t &trackIndex, std::shared_ptr<Meta> trackDesc)
37{
38    Status ret;
39    if ((ret = avmuxer_->AddTrack(trackIndex, trackDesc)) != Status::OK) {
40        std::cout<<"AVMuxerEngineDemo::DoAddTrack failed! ret:"<<static_cast<int32_t>(ret)<<std::endl;
41        return -1;
42    }
43    return 0;
44}
45
46sptr<AVBufferQueueProducer> AVMuxerEngineDemo::DoGetInputBufferQueue(uint32_t trackIndex)
47{
48    std::cout<<"AVMuxerEngineDemo::DoGetInputBufferQueue "<<trackIndex<<std::endl;
49    return avmuxer_->GetInputBufferQueue(trackIndex);
50}
51
52void AVMuxerEngineDemo::DoRunMuxer(const std::string &runMode)
53{
54    std::string outFileName = GetOutputFileName("engine_mux_" + runMode);
55    outFd_ = open(outFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
56    if (outFd_ < 0) {
57        std::cout << "Open file failed! filePath is: " << outFileName << std::endl;
58        return;
59    }
60    std::cout<<"==== open success! =====\noutputFileName: "<<outFileName<<"\n============"<<std::endl;
61    long long testTimeStart = GetTimestamp();
62    avmuxer_ = std::make_shared<MediaMuxer>(-1, -1);
63    if (avmuxer_ == nullptr || avmuxer_->Init(outFd_, outputFormat_) != Status::OK) {
64        std::cout << "avmuxer_ is null" << std::endl;
65        return;
66    }
67
68    std::cout << "create muxer success " << avmuxer_ << std::endl;
69
70    SetParameter();
71    AddAudioTrack(audioParams_);
72    AddVideoTrack(videoParams_);
73    AddCoverTrack(coverParams_);
74    SetUserData();
75
76    std::cout << "add track success" << std::endl;
77
78    if (avmuxer_->Start() != Status::OK) {
79        return;
80    }
81
82    std::cout << "start muxer success" << std::endl;
83
84    WriteCoverSample();
85
86    std::cout<<"AVMuxerEngineDemo::DoRunMuxer runMode is : "<<runMode<<std::endl;
87    if (runMode.compare(RUN_NORMAL) == 0) {
88        WriteTrackSampleByBufferQueue();
89    } else if (runMode.compare(RUN_MUL_THREAD) == 0) {
90        std::vector<std::thread> vecThread;
91        vecThread.emplace_back(MulThdWriteTrackSampleByBufferQueue, this, audioBufferQueue_, audioFile_);
92        vecThread.emplace_back(MulThdWriteTrackSampleByBufferQueue, this, videoBufferQueue_, videoFile_);
93        for (uint32_t i = 0; i < vecThread.size(); ++i) {
94            vecThread[i].join();
95        }
96    }
97
98    std::cout << "write muxer success" << std::endl;
99
100    if (avmuxer_->Stop() != Status::OK) {
101        return;
102    }
103    std::cout << "stop muxer success" << std::endl;
104    long long testTimeEnd = GetTimestamp();
105    std::cout << "muxer used time: " << testTimeEnd - testTimeStart << "us" << std::endl;
106}
107
108void AVMuxerEngineDemo::DoRunMuxer()
109{
110    DoRunMuxer(std::string(RUN_NORMAL));
111}
112
113void AVMuxerEngineDemo::DoRunMultiThreadCase()
114{
115    DoRunMuxer(std::string(RUN_MUL_THREAD));
116}
117
118void AVMuxerEngineDemo::SetParameter()
119{
120    std::shared_ptr<Meta> param = std::make_shared<Meta>();
121    param->Set<Tag::VIDEO_ROTATION>(Plugins::VideoRotation::VIDEO_ROTATION_0);
122    param->Set<Tag::MEDIA_CREATION_TIME>("2023-12-19T03:16:00.000Z");
123    param->Set<Tag::MEDIA_LATITUDE>(22.67f); // 22.67f test latitude
124    param->Set<Tag::MEDIA_LONGITUDE>(114.06f); // 114.06f test longitude
125    param->Set<Tag::MEDIA_TITLE>("ohos muxer");
126    param->Set<Tag::MEDIA_ARTIST>("ohos muxer");
127    param->Set<Tag::MEDIA_COMPOSER>("ohos muxer");
128    param->Set<Tag::MEDIA_DATE>("2023-12-19");
129    param->Set<Tag::MEDIA_ALBUM>("ohos muxer");
130    param->Set<Tag::MEDIA_ALBUM_ARTIST>("ohos muxer");
131    param->Set<Tag::MEDIA_COPYRIGHT>("ohos muxer");
132    param->Set<Tag::MEDIA_GENRE>("{marketing-name:\"HW P60\"}");
133    if (avmuxer_->SetParameter(param) != Status::OK) {
134        std::cout<<"set parameter failed!"<<std::endl;
135    }
136}
137
138void AVMuxerEngineDemo::SetUserData()
139{
140    std::shared_ptr<Meta> userMeta = std::make_shared<Meta>();
141    userMeta->SetData("com.openharmony.version", 5); // 5 test version
142    userMeta->SetData("com.openharmony.model", "LNA-AL00");
143    userMeta->SetData("com.openharmony.manufacturer", "HW");
144    userMeta->SetData("com.openharmony.marketing_name", "HW P60");
145    userMeta->SetData("com.openharmony.capture.fps", 30.00f); // 30.00f test capture fps
146    userMeta->SetData("model", "LNA-AL00");
147    userMeta->SetData("com.openharmony.flag", true);
148    if (avmuxer_->SetUserMeta(userMeta) != Status::OK) {
149        std::cout<<"set user meta failed!"<<std::endl;
150    }
151}
152}  // namespace MediaAVCodec
153}  // namespace OHOS