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
16 #include "avcodec_audio_avbuffer_lbvc_decoder_inner_demo.h"
17 #include <unistd.h>
18 #include <string>
19 #include <string_view>
20 #include <iostream>
21 #include <unistd.h>
22 #include <chrono>
23 #include "securec.h"
24 #include "demo_log.h"
25 #include "meta/audio_types.h"
26 #include "inner_api/native/avcodec_audio_codec.h"
27 #include "avcodec_errors.h"
28
29 using namespace OHOS::Media;
30 using namespace OHOS::MediaAVCodec;
31 using namespace OHOS::MediaAVCodec::InnerAudioDecoderLbvcDemo;
32
33 namespace {
34 constexpr std::string_view INPUT_FILE_PATH = "/data/test/media/lbvc_1c_16000hz_6k.dat";
35 constexpr std::string_view OUTPUT_PCM_FILE_PATH = "/data/test/media/lbvc_1c_16000hz_6k_test.pcm";
36
37 constexpr int32_t INPUT_FRAME_BYTES = 160 * 4;
38 constexpr int32_t TIME_OUT_MS = 8;
39
40 typedef enum OH_AVCodecBufferFlags {
41 AVCODEC_BUFFER_FLAGS_NONE = 0,
42 /* Indicates that the Buffer is an End-of-Stream frame */
43 AVCODEC_BUFFER_FLAGS_EOS = 1 << 0,
44 /* Indicates that the Buffer contains keyframes */
45 AVCODEC_BUFFER_FLAGS_SYNC_FRAME = 1 << 1,
46 /* Indicates that the data contained in the Buffer is only part of a frame */
47 AVCODEC_BUFFER_FLAGS_INCOMPLETE_FRAME = 1 << 2,
48 /* Indicates that the Buffer contains Codec-Specific-Data */
49 AVCODEC_BUFFER_FLAGS_CODEC_DATA = 1 << 3,
50 } OH_AVCodecBufferFlags;
51 } // namespace
52
GetFileSize(const std::string & filePath)53 static int32_t GetFileSize(const std::string &filePath)
54 {
55 std::ifstream file(filePath, std::ios::binary | std::ios::ate);
56 if (!file) {
57 std::cerr << "Failed to open file:" << filePath << std::endl;
58 return -1;
59 }
60
61 std::streampos fileSize = file.tellg(); // 获取文件大小
62 file.close();
63
64 return (int32_t)fileSize;
65 }
66
AudioCodecConsumerListener(AudioDecInnerAvBufferLbvcDemo * demo)67 AudioCodecConsumerListener::AudioCodecConsumerListener(AudioDecInnerAvBufferLbvcDemo *demo)
68 {
69 demo_ = demo;
70 }
71
OnBufferAvailable()72 void AudioCodecConsumerListener::OnBufferAvailable()
73 {
74 demo_->OutputFunc();
75 }
76
RunCase()77 void AudioDecInnerAvBufferLbvcDemo::RunCase()
78 {
79 innerBufferQueue_ = Media::AVBufferQueue::Create(4, Media::MemoryType::SHARED_MEMORY, "InnerDemo"); // 4
80
81 audiocodec_ = AudioCodecFactory::CreateByName("OH.Media.Codec.Decoder.Audio.LBVC");
82 if (audiocodec_ == nullptr) {
83 std::cout << "codec == nullptr" << std::endl;
84 return;
85 }
86 auto meta = std::make_shared<Media::Meta>();
87 meta->Set<Tag::AUDIO_CHANNEL_COUNT>(1); // CHANNEL_COUNT is 1
88 meta->Set<Tag::AUDIO_SAMPLE_FORMAT>(Media::Plugins::AudioSampleFormat::SAMPLE_S16LE);
89 meta->Set<Tag::AUDIO_SAMPLE_RATE>(16000); // SAMPLE_RATE is 16000
90 audiocodec_->Configure(meta);
91
92 audiocodec_->SetOutputBufferQueue(innerBufferQueue_->GetProducer());
93 audiocodec_->Prepare();
94
95 implConsumer_ = innerBufferQueue_->GetConsumer();
96 sptr<Media::IConsumerListener> comsumerListener = new AudioCodecConsumerListener(this);
97 implConsumer_->SetBufferAvailableListener(comsumerListener);
98 mediaCodecProducer_ = audiocodec_->GetInputBufferQueue();
99
100 audiocodec_->Start();
101 isRunning_.store(true);
102
103 fileSize_ = GetFileSize(INPUT_FILE_PATH.data());
104 inputFile_ = std::make_unique<std::ifstream>(INPUT_FILE_PATH, std::ios::binary);
105 outputFile_ = std::make_unique<std::ofstream>(OUTPUT_PCM_FILE_PATH, std::ios::binary);
106 InputFunc();
107 inputFile_->close();
108 outputFile_->close();
109 audiocodec_->Stop();
110 audiocodec_->Release();
111 return;
112 }
113
GetInputBufferSize()114 int32_t AudioDecInnerAvBufferLbvcDemo::GetInputBufferSize()
115 {
116 int32_t capacity = 0;
117 DEMO_CHECK_AND_RETURN_RET_LOG(audiocodec_ != nullptr, capacity, "audiocodec_ is nullptr");
118 std::shared_ptr<Media::Meta> bufferConfig = std::make_shared<Media::Meta>();
119 DEMO_CHECK_AND_RETURN_RET_LOG(bufferConfig != nullptr, capacity, "bufferConfig is nullptr");
120 int32_t ret = audiocodec_->GetOutputFormat(bufferConfig);
121 DEMO_CHECK_AND_RETURN_RET_LOG(ret == AVCodecServiceErrCode::AVCS_ERR_OK, capacity, "GetOutputFormat fail");
122 DEMO_CHECK_AND_RETURN_RET_LOG(bufferConfig->Get<Media::Tag::AUDIO_MAX_INPUT_SIZE>(capacity),
123 capacity, "get max input buffer size fail");
124 return capacity;
125 }
126
InputFunc()127 void AudioDecInnerAvBufferLbvcDemo::InputFunc()
128 {
129 DEMO_CHECK_AND_RETURN_LOG(inputFile_ != nullptr && inputFile_->is_open(), "Fatal: open file fail");
130 int32_t sumReadSize = 0;
131 Media::Status ret;
132 int64_t size;
133 int64_t pts;
134 Media::AVBufferConfig avBufferConfig;
135 avBufferConfig.size = GetInputBufferSize();
136 while (isRunning_) {
137 std::shared_ptr<AVBuffer> inputBuffer = nullptr;
138 DEMO_CHECK_AND_BREAK_LOG(mediaCodecProducer_ != nullptr, "mediaCodecProducer_ is nullptr");
139 ret = mediaCodecProducer_->RequestBuffer(inputBuffer, avBufferConfig, TIME_OUT_MS);
140 if (ret != Media::Status::OK) {
141 std::cout << "produceInputBuffer RequestBuffer fail,ret=" << (int32_t)ret << std::endl;
142 break;
143 }
144 DEMO_CHECK_AND_BREAK_LOG(inputBuffer != nullptr, "buffer is nullptr");
145 inputFile_->read(reinterpret_cast<char *>(&size), sizeof(size));
146 if (inputFile_->eof() || inputFile_->gcount() == 0 || size == 0) {
147 inputBuffer->memory_->SetSize(1);
148 inputBuffer->flag_ = AVCODEC_BUFFER_FLAGS_EOS;
149 sumReadSize += 0;
150 mediaCodecProducer_->PushBuffer(inputBuffer, true);
151 sumReadSize += inputFile_->gcount();
152 std::cout << "InputFunc, INPUT_FRAME_BYTES:" << INPUT_FRAME_BYTES << " flag:" << inputBuffer->flag_
153 << " sumReadSize:" << sumReadSize << " fileSize_:" << fileSize_
154 << " process:" << 100 * sumReadSize / fileSize_ << "%" << std::endl; // 100
155 std::cout << "end buffer\n";
156 break;
157 }
158 DEMO_CHECK_AND_BREAK_LOG(inputFile_->gcount() == sizeof(size), "Fatal: read size fail");
159 sumReadSize += inputFile_->gcount();
160 inputFile_->read(reinterpret_cast<char *>(&pts), sizeof(pts));
161 DEMO_CHECK_AND_BREAK_LOG(inputFile_->gcount() == sizeof(pts), "Fatal: read pts fail");
162 sumReadSize += inputFile_->gcount();
163 inputFile_->read(reinterpret_cast<char *>(inputBuffer->memory_->GetAddr()), size);
164 DEMO_CHECK_AND_BREAK_LOG(inputFile_->gcount() == size, "Fatal: read buffer fail");
165 inputBuffer->memory_->SetSize(size);
166 inputBuffer->flag_ = AVCODEC_BUFFER_FLAGS_NONE;
167 sumReadSize += inputFile_->gcount();
168 mediaCodecProducer_->PushBuffer(inputBuffer, true);
169 std::cout << "InputFunc, INPUT_FRAME_BYTES:" << INPUT_FRAME_BYTES << " flag:" << inputBuffer->flag_
170 << " sumReadSize:" << sumReadSize << " fileSize_:" << fileSize_
171 << " process:" << 100 * sumReadSize / fileSize_ << "%" << std::endl; // 100
172 }
173 }
174
OutputFunc()175 void AudioDecInnerAvBufferLbvcDemo::OutputFunc()
176 {
177 bufferConsumerAvailableCount_++;
178 Media::Status ret = Media::Status::OK;
179 while (isRunning_ && (bufferConsumerAvailableCount_ > 0)) {
180 std::cout << "/**********ImplConsumerOutputBuffer while**********/" << std::endl;
181 std::shared_ptr<AVBuffer> outputBuffer;
182 ret = implConsumer_->AcquireBuffer(outputBuffer);
183 if (ret != Media::Status::OK) {
184 std::cout << "Consumer AcquireBuffer fail,ret=" << (int32_t)ret << std::endl;
185 break;
186 }
187 if (outputBuffer == nullptr) {
188 std::cout << "OutputFunc OH_AVBuffer is nullptr" << std::endl;
189 continue;
190 }
191 outputFile_->write(reinterpret_cast<char *>(outputBuffer->memory_->GetAddr()),
192 outputBuffer->memory_->GetSize());
193 if (outputBuffer->flag_ == AVCODEC_BUFFER_FLAGS_EOS || outputBuffer->memory_->GetSize() == 0) {
194 std::cout << "out eos" << std::endl;
195 isRunning_.store(false);
196 }
197 implConsumer_->ReleaseBuffer(outputBuffer);
198 bufferConsumerAvailableCount_--;
199 }
200 }