/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "avmuxer_demo_base.h" #include #include #include #include "avcodec_errors.h" namespace { constexpr int MODE_ZERO = 0; constexpr int MODE_ONE = 1; constexpr int MODE_TWO = 2; constexpr int MODE_THREE = 3; constexpr int MODE_FOUR = 4; constexpr int CONFIG_BUFFER_SZIE = 0x1FFF; } namespace OHOS { namespace MediaAVCodec { const AudioTrackParam *AVMuxerDemoBase::audioParams_ = nullptr; const VideoTrackParam *AVMuxerDemoBase::videoParams_ = nullptr; const VideoTrackParam *AVMuxerDemoBase::coverParams_ = nullptr; std::string AVMuxerDemoBase::videoType_ = std::string(""); std::string AVMuxerDemoBase::audioType_ = std::string(""); std::string AVMuxerDemoBase::coverType_ = std::string(""); std::string AVMuxerDemoBase::format_ = std::string(""); Plugins::OutputFormat AVMuxerDemoBase::outputFormat_ = Plugins::OutputFormat::DEFAULT; bool AVMuxerDemoBase::hasSetMode_ = false; using namespace OHOS::Media; AVMuxerDemoBase::AVMuxerDemoBase() { } std::shared_ptr OpenFile(const std::string &filePath) { auto file = std::make_shared(); file->open(filePath, std::ios::in | std::ios::binary); if (file->is_open()) { return file; } return nullptr; } void AVMuxerDemoBase::SelectFormatMode() { int num; std::cout<<"\nplease select muxer type: 0.mp4 1.m4a 2.amr 3.mp3"<>num; switch (num) { case MODE_ZERO: format_ = "mp4"; outputFormat_ = Plugins::OutputFormat::MPEG_4; break; case MODE_ONE: format_ = "m4a"; outputFormat_ = Plugins::OutputFormat::M4A; break; case MODE_TWO: format_ = "amr"; outputFormat_ = Plugins::OutputFormat::AMR; break; case MODE_THREE: format_ = "mp3"; outputFormat_ = Plugins::OutputFormat::MP3; break; default: format_ = "mp4"; outputFormat_ = Plugins::OutputFormat::MPEG_4; break; } } void AVMuxerDemoBase::SelectAudioMode() { int num; std::cout<<"\nplease select audio file: 0.noAudio 1.aac 2.mpeg 3.amrnb 4.amrwb"<>num; switch (num) { case MODE_ZERO: audioType_ = "noAudio"; audioParams_ = nullptr; break; case MODE_ONE: audioType_ = "aac"; audioParams_ = &g_audioAacPar; break; case MODE_TWO: audioType_ = "mpeg"; audioParams_ = &g_audioMpegPar; break; case MODE_THREE: audioType_ = "amr"; audioParams_ = &g_audioAmrNbPar; break; case MODE_FOUR: audioType_ = "amr"; audioParams_ = &g_audioAmrWbPar; break; default: audioType_ = "noAudio"; audioParams_ = nullptr; std::cout<<"do not support audio type index: "<>num; switch (num) { case MODE_ZERO: videoType_ = "noVideo"; videoParams_ = nullptr; break; case MODE_ONE: videoType_ = "h264"; videoParams_ = &g_videoH264Par; break; case MODE_TWO: videoType_ = "mpeg4"; videoParams_ = &g_videoMpeg4Par; break; case MODE_THREE: videoType_ = "h265"; videoParams_ = &g_videoH265Par; break; case MODE_FOUR: videoType_ = "hdr-vivid"; videoParams_ = &g_videoHdrPar; break; default: videoType_ = "noVideo"; videoParams_ = nullptr; std::cout<<"do not support video type index: "<<", set to noVideo"<>num; switch (num) { case MODE_ZERO: coverType_ = "noCover"; coverParams_ = nullptr; break; case MODE_ONE: coverType_ = "jpg"; coverParams_ = &g_jpegCoverPar; break; case MODE_TWO: coverType_ = "png"; coverParams_ = &g_pngCoverPar; break; case MODE_THREE: coverType_ = "bmp"; coverParams_ = &g_bmpCoverPar; break; default: coverType_ = "noCover"; coverParams_ = nullptr; std::cout<<"do not support cover type index: "<<", set to noCover"<fileName); if (audioFile_ == nullptr) { std::cout<<"open audio file failed! file name:"<fileName<fileName<fileName); if (videoFile_ == nullptr) { std::cout<<"open video file failed! file name:"<fileName<fileName<fileName); if (coverFile_ == nullptr) { std::cout<<"open cover file failed! file name:"<fileName<fileName< 0) { close(outFd_); outFd_ = -1; } if (audioFile_ != nullptr) { audioFile_->close(); audioFile_ = nullptr; } if (videoFile_ != nullptr) { videoFile_->close(); videoFile_ = nullptr; } if (coverFile_ != nullptr) { coverFile_->close(); coverFile_ = nullptr; } } void AVMuxerDemoBase::RunCase() { if (SelectModeAndOpenFile() != 0) { return; } DoRunMuxer(); Reset(); } void AVMuxerDemoBase::RunMultiThreadCase() { std::cout<<"==== start AVMuxerDemoBase::RunMultiThreadCase ==="< file) { if (file == nullptr) { std::cout<<"AVMuxerDemoBase::WriteTrackSample file is nullptr"< buffer = nullptr; bool ret = ReadSampleDataInfo(file, buffer); while (ret) { if (DoWriteSample(trackId, buffer) != AVCS_ERR_OK) { std::cout<<"WriteSample failed"< bufferQueue, std::shared_ptr file) { if (file == nullptr) { std::cout<<"AVMuxerDemoBase::WriteSingleTrackSampleByBufferQueue file is nullptr"< buffer = nullptr; if (bufferQueue == nullptr) { std::cout<<"AVMuxerDemoBase::WriteSingleTrackSampleByBufferQueue buffer queue is nullptr"<PushBuffer(buffer, true) != Status::OK) { std::cout<<"BufferQueue PushBuffer failed"< file, std::shared_ptr &buffer) { int64_t pts = 0; uint32_t flags = 0; int32_t size = 0; if (file->eof()) { return false; } file->read(reinterpret_cast(&pts), sizeof(pts)); if (file->eof()) { return false; } file->read(reinterpret_cast(&flags), sizeof(flags)); if (file->eof()) { return false; } file->read(reinterpret_cast(&size), sizeof(size)); if (file->eof()) { return false; } if (buffer == nullptr || buffer->memory_ == nullptr || buffer->memory_->GetCapacity() < size) { auto alloc = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); buffer = AVBuffer::CreateAVBuffer(alloc, size); } file->read(reinterpret_cast(buffer->memory_->GetAddr()), size); buffer->pts_ = pts; buffer->flag_ = flags; buffer->memory_->SetSize(size); return true; } bool AVMuxerDemoBase::ReadSampleDataInfoByBufferQueue(std::shared_ptr file, std::shared_ptr &buffer, sptr bufferQueue) { int64_t pts = 0; uint32_t flags = 0; int32_t size = 0; if (file->eof()) { return false; } file->read(reinterpret_cast(&pts), sizeof(pts)); if (file->eof()) { return false; } file->read(reinterpret_cast(&flags), sizeof(flags)); if (file->eof()) { return false; } file->read(reinterpret_cast(&size), sizeof(size)); if (file->eof()) { return false; } if (bufferQueue == nullptr) { return false; } AVBufferConfig config; config.size = size; config.memoryType = MemoryType::VIRTUAL_MEMORY; bufferQueue->RequestBuffer(buffer, config, -1); file->read(reinterpret_cast(buffer->memory_->GetAddr()), size); buffer->pts_ = pts; buffer->flag_ = flags; buffer->memory_->SetSize(size); return true; } void AVMuxerDemoBase::WriteAvTrackSample() { if (audioFile_ == nullptr || videoFile_ == nullptr) { return; } std::shared_ptr audioBuffer = nullptr; std::shared_ptr videoBuffer = nullptr; bool audioRet = ReadSampleDataInfo(audioFile_, audioBuffer); bool videoRet = ReadSampleDataInfo(videoFile_, videoBuffer); bool isOver = false; while (!isOver && (audioRet || videoRet)) { int ret = AVCS_ERR_OK; if (audioRet && videoRet && audioBuffer->pts_ <= videoBuffer->pts_) { ret = DoWriteSample(audioTrackId_, audioBuffer); audioRet = ReadSampleDataInfo(audioFile_, audioBuffer); } else if (audioRet && videoRet) { ret = DoWriteSample(videoTrackId_, videoBuffer); videoRet = ReadSampleDataInfo(videoFile_, videoBuffer); } else if (audioRet) { ret = DoWriteSample(audioTrackId_, audioBuffer); isOver = true; } else { ret = DoWriteSample(videoTrackId_, videoBuffer); isOver = true; } if (ret != AVCS_ERR_OK) { std::cout<<"WriteSample failed"< audioBuffer = nullptr; std::shared_ptr videoBuffer = nullptr; bool audioRet = ReadSampleDataInfoByBufferQueue(audioFile_, audioBuffer, audioBufferQueue_); bool videoRet = ReadSampleDataInfoByBufferQueue(videoFile_, videoBuffer, videoBufferQueue_); bool isOver = false; Status ret = Status::OK; while (!isOver && (audioRet || videoRet)) { if (audioRet && videoRet && audioBuffer->pts_ <= videoBuffer->pts_) { ret = audioBufferQueue_->PushBuffer(audioBuffer, true); audioRet = ReadSampleDataInfoByBufferQueue(audioFile_, audioBuffer, audioBufferQueue_); } else if (audioRet && videoRet) { ret = videoBufferQueue_->PushBuffer(videoBuffer, true); videoRet = ReadSampleDataInfoByBufferQueue(videoFile_, videoBuffer, videoBufferQueue_); } else if (audioRet) { ret = audioBufferQueue_->PushBuffer(audioBuffer, true); isOver = true; } else { ret = videoBufferQueue_->PushBuffer(videoBuffer, true); isOver = true; } if (ret != Status::OK) { std::cout<<"BufferQueue PushBuffer failed"<= 0 && videoTrackId_ >= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO and VIDEO sample"<= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSample write AUDIO sample"<= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSample write VIDEO sample"<= 0 && videoTrackId_ >= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSampleByBufferQueue write AUDIO and VIDEO sample"<= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSampleByBufferQueue write AUDIO sample"<= 0) { std::cout<<"AVMuxerDemoBase::WriteTrackSampleByBufferQueue write VIDEO sample"< file) { muxerBase->WriteSingleTrackSample(trackId, file); } void AVMuxerDemoBase::MulThdWriteTrackSampleByBufferQueue(AVMuxerDemoBase *muxerBase, sptr bufferQueue, std::shared_ptr file) { muxerBase->WriteSingleTrackSampleByBufferQueue(bufferQueue, file); } void AVMuxerDemoBase::WriteCoverSample() { if (coverParams_ == nullptr) { return; } std::cout<<"AVMuxerDemoBase::WriteCoverSample"<seekg(0, std::ios::end); int32_t size = coverFile_->tellg(); coverFile_->seekg(0, std::ios::beg); if (size <= 0) { std::cout<<"AVMuxerDemoBase::WriteCoverSample coverFile_ size is 0!"< avMemBuffer = AVBuffer::CreateAVBuffer(alloc, size); coverFile_->read(reinterpret_cast(avMemBuffer->memory_->GetAddr()), size); avMemBuffer->pts_ = 0; avMemBuffer->memory_->SetSize(size); if (DoWriteSample(coverTrackId_, avMemBuffer) != AVCS_ERR_OK) { std::cout<<"WriteCoverSample error"< videoParams = std::make_shared(); videoParams->Set(param->mimeType); videoParams->Set(param->width); videoParams->Set(param->height); videoParams->Set(param->frameRate); videoParams->Set(param->videoDelay); if (param == &g_videoHdrPar) { videoParams->Set(static_cast(param->colorPrimaries)); videoParams->Set(static_cast(param->colorTransfer)); videoParams->Set( static_cast(param->colorMatrixCoeff)); videoParams->Set(static_cast(param->colorRange)); videoParams->Set(static_cast(param->isHdrVivid)); } int extSize = 0; videoFile_->read(reinterpret_cast(&extSize), sizeof(extSize)); if (extSize > 0 && extSize < CONFIG_BUFFER_SZIE) { std::vector buffer(extSize); videoFile_->read(reinterpret_cast(buffer.data()), extSize); videoParams->Set(buffer); } else { std::cout<<"AVMuxerDemoBase::AddVideoTrack DoAddTrack failed!"< audioParams = std::make_shared(); audioParams->Set(param->mimeType); audioParams->Set(param->sampleRate); audioParams->Set(param->channels); audioParams->Set(param->frameSize); if (param == &g_audioAacPar) { audioParams->Set(Plugins::AACProfile::AAC_PROFILE_LC); } int extSize = 0; audioFile_->read(reinterpret_cast(&extSize), sizeof(extSize)); if (extSize > 0 && extSize < CONFIG_BUFFER_SZIE) { std::vector buffer(extSize); audioFile_->read(reinterpret_cast(buffer.data()), extSize); audioParams->Set(buffer); } else { std::cout<<"AVMuxerDemoBase::AddAudioTrack error extSize:"< coverParams = std::make_shared(); coverParams->Set(param->mimeType); coverParams->Set(param->width); coverParams->Set(param->height); if (DoAddTrack(coverTrackId_, coverParams) != AVCS_ERR_OK) { return -1; } std::cout << "AVMuxerDemoBase::AddCoverTrack video trackId is: " << coverTrackId_ << std::endl; coverBufferQueue_ = DoGetInputBufferQueue(coverTrackId_); return 0; } std::string AVMuxerDemoBase::GetOutputFileName(std::string header) { std::string outputFileName = header; if (!audioType_.empty()) { outputFileName += "_" + audioType_; } if (!videoType_.empty()) { outputFileName += "_" + videoType_; } if (!coverType_.empty()) { outputFileName += "_" + coverType_; } outputFileName += "." + format_; return outputFileName; } } // MediaAVCodec } // OHOS