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 "hdrcodec_sample.h"
16 #include <iostream>
17 #include <string>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <list>
22 #include <arpa/inet.h>
23 #include <sys/time.h>
24 #include <utility>
25 #include <memory>
26
27 #include "av_common.h"
28
29 #include "avcodec_common.h"
30 #include "native_avdemuxer.h"
31 #include "native_avsource.h"
32 #include "native_avmuxer.h"
33 #include "avcodec_errors.h"
34 #include "native_avformat.h"
35 #include "native_avcodec_base.h"
36 #include "media_description.h"
37 #include "native_avmemory.h"
38 #include "native_averrors.h"
39 #include "surface/window.h"
40 #include "openssl/crypto.h"
41 #include "openssl/sha.h"
42 using namespace OHOS;
43 using namespace OHOS::Media;
44 using namespace std;
45 namespace {
46 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
47 constexpr int64_t NANOS_IN_MICRO = 1000L;
48 std::shared_ptr<std::ifstream> inFile_;
49 std::condition_variable g_cv;
50 std::atomic<bool> g_isRunning = true;
51 constexpr uint32_t START_CODE_SIZE = 4;
52 constexpr int32_t EIGHT = 8;
53 constexpr int32_t SIXTEEN = 16;
54 constexpr int32_t TWENTY_FOUR = 24;
55 constexpr uint8_t H264_NALU_TYPE = 0x1f;
56 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
57 constexpr uint8_t SPS = 7;
58 constexpr uint8_t PPS = 8;
59 constexpr uint8_t MPEG2_FRAME_HEAD[] = {0x00, 0x00, 0x01, 0x00};
60 constexpr uint8_t MPEG2_SEQUENCE_HEAD[] = {0x00, 0x00, 0x01, 0xb3};
61 constexpr uint8_t MPEG4_FRAME_HEAD[] = {0x00, 0x00, 0x01, 0xb6};
62 constexpr uint8_t MPEG4_SEQUENCE_HEAD[] = {0x00, 0x00, 0x01, 0xb0};
63 constexpr uint32_t PREREAD_BUFFER_SIZE = 0.1 * 1024 * 1024;
64 constexpr uint32_t MAX_WIDTH = 4000;
65 constexpr uint32_t MAX_HEIGHT = 3000;
66 constexpr uint32_t MAX_NALU_SIZE = MAX_WIDTH * MAX_HEIGHT << 1;
67 constexpr int32_t AUDIO_BUFFER_SIZE = 1024 * 1024;
68 constexpr int32_t CHANNEL_0 = 0;
69 constexpr int32_t CHANNEL_1 = 1;
70 constexpr int32_t CHANNEL_2 = 2;
71 constexpr int32_t CHANNEL_3 = 3;
72 constexpr int32_t CHANNEL_4 = 4;
73 }
74
GetSystemTimeUs()75 int64_t GetSystemTimeUs()
76 {
77 struct timespec now;
78 (void)clock_gettime(CLOCK_BOOTTIME, &now);
79 int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
80
81 return nanoTime / NANOS_IN_MICRO;
82 }
83
VdecFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)84 void VdecFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
85 {
86 cout << "Format Changed" << endl;
87 }
88
VdecInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)89 void VdecInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
90 {
91 HDRCodecNdkSample *sample = static_cast<HDRCodecNdkSample *>(userData);
92 VSignal *signal = sample->decSignal;
93 unique_lock<mutex> lock(signal->inMutex_);
94 if (sample->DEMUXER_FLAG) {
95 OH_AVCodecBufferAttr attr;
96 OH_AVDemuxer_ReadSample(sample->demuxer, sample->videoTrackID, data, &attr);
97 OH_VideoDecoder_PushInputData(codec, index, attr);
98 } else {
99 signal->inIdxQueue_.push(index);
100 signal->inBufferQueue_.push(data);
101 signal->inCond_.notify_all();
102 }
103 }
104
VdecOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)105 void VdecOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
106 void *userData)
107 {
108 HDRCodecNdkSample *sample = static_cast<HDRCodecNdkSample *>(userData);
109 if (attr->flags & AVCODEC_BUFFER_FLAGS_EOS) {
110 OH_VideoEncoder_NotifyEndOfStream(sample->venc_);
111 } else {
112 OH_VideoDecoder_RenderOutputData(codec, index);
113 sample->frameCountDec++;
114 }
115 }
116
VdecError(OH_AVCodec * codec,int32_t errorCode,void * userData)117 void VdecError(OH_AVCodec *codec, int32_t errorCode, void *userData)
118 {
119 HDRCodecNdkSample *sample = static_cast<HDRCodecNdkSample *>(userData);
120 sample->errorCount++;
121 cout << "VdecError errorCode=" << errorCode << endl;
122 g_isRunning.store(false);
123 g_cv.notify_all();
124 }
125
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)126 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
127 {
128 HDRCodecNdkSample *sample = static_cast<HDRCodecNdkSample *>(userData);
129 sample->errorCount++;
130 cout << "VencError errorCode=" << errorCode << endl;
131 g_isRunning.store(false);
132 g_cv.notify_all();
133 }
134
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)135 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
136 {
137 cout << "Format Changed" << endl;
138 }
139
VencInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)140 static void VencInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
141 {
142 (void)codec;
143 (void)index;
144 (void)data;
145 (void)userData;
146 }
147
VencOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)148 static void VencOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
149 void *userData)
150 {
151 HDRCodecNdkSample *sample = static_cast<HDRCodecNdkSample*>(userData);
152 OH_VideoEncoder_FreeOutputData(codec, index);
153 if (attr->flags & AVCODEC_BUFFER_FLAGS_EOS) {
154 g_isRunning.store(false);
155 g_cv.notify_all();
156 } else if (attr->flags != AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
157 sample->frameCountEnc++;
158 }
159 if (sample->DEMUXER_FLAG) {
160 OH_AVMuxer_WriteSample(sample->muxer, sample->videoTrackID, data, *attr);
161 }
162 }
163
clearIntqueue(std::queue<uint32_t> & q)164 static void clearIntqueue(std::queue<uint32_t> &q)
165 {
166 std::queue<uint32_t> empty;
167 swap(empty, q);
168 }
169
PtrStep(uint32_t & bufferSize,unsigned char ** pBuffer,uint32_t size)170 void HDRCodecNdkSample::PtrStep(uint32_t &bufferSize, unsigned char **pBuffer, uint32_t size)
171 {
172 pPrereadBuffer_ += size;
173 bufferSize += size;
174 *pBuffer += size;
175 }
176
PtrStepExtraRead(uint32_t & bufferSize,unsigned char ** pBuffer)177 void HDRCodecNdkSample::PtrStepExtraRead(uint32_t &bufferSize, unsigned char **pBuffer)
178 {
179 bufferSize -= START_CODE_SIZE;
180 *pBuffer -= START_CODE_SIZE;
181 pPrereadBuffer_ = 0;
182 }
183
GetMpeg4BufferSize()184 void HDRCodecNdkSample::GetMpeg4BufferSize()
185 {
186 auto pBuffer = mpegUnit_->data();
187 uint32_t bufferSize = 0;
188 mpegUnit_->resize(MAX_NALU_SIZE);
189 do {
190 auto pos1 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + START_CODE_SIZE,
191 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG4_FRAME_HEAD), std::end(MPEG4_FRAME_HEAD));
192 uint32_t size1 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos1);
193 auto pos2 = std::search(prereadBuffer_.get() + pPrereadBuffer_, prereadBuffer_.get() +
194 pPrereadBuffer_ + size1, std::begin(MPEG4_SEQUENCE_HEAD), std::end(MPEG4_SEQUENCE_HEAD));
195 uint32_t size = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos2);
196 if (size == 0) {
197 auto pos3 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + size1 + START_CODE_SIZE,
198 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG4_FRAME_HEAD), std::end(MPEG4_FRAME_HEAD));
199 uint32_t size2 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos3);
200 if (memcpy_s(pBuffer, size2, prereadBuffer_.get() + pPrereadBuffer_, size2) != EOK) {
201 return;
202 }
203 PtrStep(bufferSize, &pBuffer, size2);
204 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
205 break;
206 }
207 } else if (size1 > size) {
208 if (memcpy_s(pBuffer, size, prereadBuffer_.get() + pPrereadBuffer_, size) != EOK) {
209 return;
210 }
211 PtrStep(bufferSize, &pBuffer, size);
212 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
213 break;
214 }
215 } else {
216 if (memcpy_s(pBuffer, size1, prereadBuffer_.get() + pPrereadBuffer_, size1) != EOK) {
217 return;
218 }
219 PtrStep(bufferSize, &pBuffer, size1);
220 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
221 break;
222 }
223 }
224 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
225 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
226 pPrereadBuffer_ = START_CODE_SIZE;
227 if (memcpy_s(prereadBuffer_.get(), START_CODE_SIZE, pBuffer - START_CODE_SIZE, START_CODE_SIZE) != EOK) {
228 return;
229 }
230 PtrStepExtraRead(bufferSize, &pBuffer);
231 } while (pPrereadBuffer_ != prereadBufferSize_);
232 mpegUnit_->resize(bufferSize);
233 }
234
GetBufferSize()235 void HDRCodecNdkSample::GetBufferSize()
236 {
237 auto pBuffer = mpegUnit_->data();
238 uint32_t bufferSize = 0;
239 mpegUnit_->resize(MAX_NALU_SIZE);
240 do {
241 auto pos1 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + START_CODE_SIZE,
242 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG2_FRAME_HEAD), std::end(MPEG2_FRAME_HEAD));
243 uint32_t size1 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos1);
244 auto pos2 = std::search(prereadBuffer_.get() + pPrereadBuffer_, prereadBuffer_.get() +
245 pPrereadBuffer_ + size1, std::begin(MPEG2_SEQUENCE_HEAD), std::end(MPEG2_SEQUENCE_HEAD));
246 uint32_t size = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos2);
247 if (size == 0) {
248 auto pos3 = std::search(prereadBuffer_.get() + pPrereadBuffer_ + size1 + START_CODE_SIZE,
249 prereadBuffer_.get() + prereadBufferSize_, std::begin(MPEG2_FRAME_HEAD), std::end(MPEG2_FRAME_HEAD));
250 uint32_t size2 = std::distance(prereadBuffer_.get() + pPrereadBuffer_, pos3);
251 if (memcpy_s(pBuffer, size2, prereadBuffer_.get() + pPrereadBuffer_, size2) != EOK) {
252 return;
253 }
254 PtrStep(bufferSize, &pBuffer, size2);
255 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
256 break;
257 }
258 } else if (size1 > size) {
259 if (memcpy_s(pBuffer, size, prereadBuffer_.get() + pPrereadBuffer_, size) != EOK) {
260 return;
261 }
262 PtrStep(bufferSize, &pBuffer, size);
263 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
264 break;
265 }
266 } else {
267 if (memcpy_s(pBuffer, size1, prereadBuffer_.get() + pPrereadBuffer_, size1) != EOK) {
268 return;
269 }
270 PtrStep(bufferSize, &pBuffer, size1);
271 if (!((pPrereadBuffer_ == prereadBufferSize_) && !inFile_->eof())) {
272 break;
273 }
274 }
275 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
276 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
277 pPrereadBuffer_ = START_CODE_SIZE;
278 if (memcpy_s(prereadBuffer_.get(), START_CODE_SIZE, pBuffer - START_CODE_SIZE, START_CODE_SIZE) != EOK) {
279 return;
280 }
281 PtrStepExtraRead(bufferSize, &pBuffer);
282 } while (pPrereadBuffer_ != prereadBufferSize_);
283 mpegUnit_->resize(bufferSize);
284 }
285
SendDataHdr(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)286 int32_t HDRCodecNdkSample::SendDataHdr(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
287 {
288 uint32_t bufferSize = 0;
289 int32_t result = 0;
290 OH_AVCodecBufferAttr attr;
291 static bool isFirstFrame = true;
292 (void)inFile_->read(reinterpret_cast<char *>(&bufferSize), sizeof(uint32_t));
293 if (inFile_->eof()) {
294 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
295 attr.offset = 0;
296 OH_VideoDecoder_PushInputData(codec, index, attr);
297 return 1;
298 }
299 if (isFirstFrame) {
300 attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
301 isFirstFrame = false;
302 } else {
303 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
304 }
305 int32_t size = OH_AVMemory_GetSize(data);
306 uint8_t *avBuffer = OH_AVMemory_GetAddr(data);
307 if (avBuffer == nullptr) {
308 return 0;
309 }
310 uint8_t *fileBuffer = new uint8_t[bufferSize];
311 if (fileBuffer == nullptr) {
312 cout << "Fatal: no memory" << endl;
313 delete[] fileBuffer;
314 return 0;
315 }
316 (void)inFile_->read(reinterpret_cast<char *>(fileBuffer), bufferSize);
317 if (memcpy_s(avBuffer, size, fileBuffer, bufferSize) != EOK) {
318 delete[] fileBuffer;
319 cout << "Fatal: memcpy fail" << endl;
320 return 0;
321 }
322 delete[] fileBuffer;
323 attr.pts = GetSystemTimeUs();
324 attr.size = bufferSize;
325 attr.offset = 0;
326 result = OH_VideoDecoder_PushInputData(codec, index, attr);
327 if (result != AV_ERR_OK) {
328 cout << "push input data failed,error:" << result << endl;
329 } else {
330 inputNum++;
331 }
332 return 0;
333 }
334
SendDataH263(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)335 int32_t HDRCodecNdkSample::SendDataH263(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
336 {
337 OH_AVCodecBufferAttr attr;
338 char ch[4] = {};
339 (void)inFile_->read(ch, START_CODE_SIZE);
340 if (inFile_->eof()) {
341 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
342 attr.offset = 0;
343 OH_VideoDecoder_PushInputData(codec, index, attr);
344 return 1;
345 }
346 uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
347 ((ch[0] & 0xFF) << TWENTY_FOUR));
348 if (bufferSize != 0) {
349 attr.flags = AVCODEC_BUFFER_FLAGS_SYNC_FRAME + AVCODEC_BUFFER_FLAGS_CODEC_DATA;
350 } else {
351 attr.offset = 0;
352 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
353 OH_VideoDecoder_PushInputData(codec, index, attr);
354 return 1;
355 }
356 int32_t size = OH_AVMemory_GetSize(data);
357 if (size < bufferSize) {
358 return 0;
359 }
360 uint8_t *avBuffer = OH_AVMemory_GetAddr(data);
361 if (avBuffer == nullptr) {
362 return 0;
363 }
364 uint8_t *fileBuffer = new uint8_t[bufferSize];
365 if (fileBuffer == nullptr) {
366 delete[] fileBuffer;
367 return 0;
368 }
369 (void)inFile_->read(reinterpret_cast<char *>(fileBuffer), bufferSize);
370 if (memcpy_s(avBuffer, size, fileBuffer, bufferSize) != EOK) {
371 delete[] fileBuffer;
372 return 0;
373 }
374 delete[] fileBuffer;
375 attr.pts = GetSystemTimeUs();
376 attr.size = bufferSize;
377 attr.offset = 0;
378 int32_t result = OH_VideoDecoder_PushInputData(codec, index, attr);
379 if (result != AV_ERR_OK) {
380 cout << "push input data failed,error:" << result << endl;
381 } else {
382 inputNum++;
383 }
384 return 0;
385 }
386
DecAvcPushData(OH_AVMemory * data,uint32_t bufferSize,uint8_t * fileBuffer)387 int32_t DecAvcPushData(OH_AVMemory *data, uint32_t bufferSize, uint8_t *fileBuffer)
388 {
389 int32_t size = OH_AVMemory_GetSize(data);
390 if (size < bufferSize + START_CODE_SIZE) {
391 cout << "error: size < bufferSize" << endl;
392 return 1;
393 }
394 uint8_t *avBuffer = OH_AVMemory_GetAddr(data);
395 if (avBuffer == nullptr) {
396 inFile_->clear();
397 inFile_->seekg(0, ios::beg);
398 delete[] fileBuffer;
399 return 1;
400 }
401 if (memcpy_s(avBuffer, size, fileBuffer, bufferSize + START_CODE_SIZE) != EOK) {
402 delete[] fileBuffer;
403 cout << "Fatal: memcpy fail" << endl;
404 return 1;
405 }
406 delete[] fileBuffer;
407 return 0;
408 }
409
SendDataAvc(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)410 int32_t HDRCodecNdkSample::SendDataAvc(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
411 {
412 OH_AVCodecBufferAttr attr;
413 char ch[4] = {};
414 (void)inFile_->read(ch, START_CODE_SIZE);
415 if (inFile_->eof()) {
416 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
417 attr.offset = 0;
418 OH_VideoDecoder_PushInputData(codec, index, attr);
419 return 1;
420 }
421 uint32_t bufferSize = (uint32_t)(((ch[3] & 0xFF)) | ((ch[2] & 0xFF) << EIGHT) | ((ch[1] & 0xFF) << SIXTEEN) |
422 ((ch[0] & 0xFF) << TWENTY_FOUR));
423 uint8_t *fileBuffer = new uint8_t[bufferSize + START_CODE_SIZE];
424 if (fileBuffer == nullptr) {
425 delete[] fileBuffer;
426 return 0;
427 }
428 if (memcpy_s(fileBuffer, bufferSize + START_CODE_SIZE, START_CODE, START_CODE_SIZE) != EOK) {
429 cout << "Fatal: memory copy failed" << endl;
430 }
431 (void)inFile_->read((char *)fileBuffer + START_CODE_SIZE, bufferSize);
432 if ((fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == SPS ||
433 (fileBuffer[START_CODE_SIZE] & H264_NALU_TYPE) == PPS) {
434 attr.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
435 } else {
436 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
437 }
438 if (DecAvcPushData(data, bufferSize, fileBuffer)) {
439 return 0;
440 }
441 attr.pts = GetSystemTimeUs();
442 attr.size = bufferSize + START_CODE_SIZE;
443 attr.offset = 0;
444 int32_t result = OH_VideoDecoder_PushInputData(codec, index, attr);
445 if (result != AV_ERR_OK) {
446 cout << "push input data failed,error:" << result << endl;
447 } else {
448 inputNum++;
449 }
450 return 0;
451 }
452
DecPushData(OH_AVMemory * data,uint32_t bufferSize,uint8_t * fileBuffer)453 int32_t DecPushData(OH_AVMemory *data, uint32_t bufferSize, uint8_t *fileBuffer)
454 {
455 int32_t size = OH_AVMemory_GetSize(data);
456 if (size < bufferSize) {
457 cout << "error: size < bufferSize" << endl;
458 inFile_->clear();
459 inFile_->seekg(0, ios::beg);
460 delete[] fileBuffer;
461 return 1;
462 }
463 uint8_t *avBuffer = OH_AVMemory_GetAddr(data);
464 if (avBuffer == nullptr) {
465 cout << "avBuffer == nullptr" << endl;
466 inFile_->clear();
467 inFile_->seekg(0, ios::beg);
468 delete[] fileBuffer;
469 return 1;
470 }
471 if (memcpy_s(avBuffer, size, fileBuffer, bufferSize) != EOK) {
472 delete[] fileBuffer;
473 cout << "Fatal: memcpy fail" << endl;
474 return 1;
475 }
476 delete[] fileBuffer;
477 return 0;
478 }
479
SendDataMpeg2(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)480 int32_t HDRCodecNdkSample::SendDataMpeg2(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
481 {
482 uint32_t bufferSize = 0;
483 int32_t result = 0;
484 OH_AVCodecBufferAttr attr;
485 if (inFile_->tellg() == 0) {
486 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
487 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
488 pPrereadBuffer_ = START_CODE_SIZE;
489 }
490 if (finishLastPush) {
491 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
492 attr.offset = 0;
493 OH_VideoDecoder_PushInputData(codec, index, attr);
494 mpegUnit_->resize(0);
495 return 1;
496 }
497 GetBufferSize();
498 bufferSize = mpegUnit_->size();
499 uint8_t *fileBuffer = nullptr;
500 if (bufferSize > 0) {
501 fileBuffer = new uint8_t[bufferSize];
502 } else {
503 delete[] fileBuffer;
504 return 0;
505 }
506 if (memcpy_s(fileBuffer, bufferSize, mpegUnit_->data(), bufferSize) != EOK) {
507 cout << "Fatal: memcpy copy fail" << endl;
508 }
509 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
510 if (pPrereadBuffer_ == prereadBufferSize_ && inFile_->eof()) {
511 finishLastPush = true;
512 }
513 if (DecPushData(data, bufferSize, fileBuffer)) {
514 return 0;
515 }
516 attr.pts = GetSystemTimeUs();
517 attr.size = bufferSize;
518 attr.offset = 0;
519 result = OH_VideoDecoder_PushInputData(codec, index, attr);
520 if (result != AV_ERR_OK) {
521 cout << "push input data failed,error:" << result << endl;
522 } else {
523 inputNum++;
524 }
525 return 0;
526 }
527
SendDataMpeg4(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)528 int32_t HDRCodecNdkSample::SendDataMpeg4(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
529 {
530 uint32_t bufferSize = 0;
531 int32_t result = 0;
532 OH_AVCodecBufferAttr attr;
533 if (inFile_->tellg() == 0) {
534 inFile_->read(reinterpret_cast<char *>(prereadBuffer_.get() + START_CODE_SIZE), PREREAD_BUFFER_SIZE);
535 prereadBufferSize_ = inFile_->gcount() + START_CODE_SIZE;
536 pPrereadBuffer_ = START_CODE_SIZE;
537 }
538 if (finishLastPush) {
539 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
540 attr.offset = 0;
541 OH_VideoDecoder_PushInputData(codec, index, attr);
542 mpegUnit_->resize(0);
543 return 1;
544 }
545 GetMpeg4BufferSize();
546 bufferSize = mpegUnit_->size();
547 if (bufferSize > MAX_WIDTH * MAX_HEIGHT << 1) {
548 return 1;
549 }
550 uint8_t *fileBuffer = nullptr;
551 if (bufferSize > 0) {
552 fileBuffer = new uint8_t[bufferSize];
553 } else {
554 delete[] fileBuffer;
555 return 0;
556 }
557 if (memcpy_s(fileBuffer, bufferSize, mpegUnit_->data(), bufferSize) != EOK) {
558 cout << "Fatal: memcpy copy fail" << endl;
559 }
560 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
561 if (pPrereadBuffer_ == prereadBufferSize_ && inFile_->eof()) {
562 finishLastPush = true;
563 }
564 if (DecPushData(data, bufferSize, fileBuffer)) {
565 return 0;
566 }
567 attr.pts = GetSystemTimeUs();
568 attr.size = bufferSize;
569 attr.offset = 0;
570 result = OH_VideoDecoder_PushInputData(codec, index, attr);
571 if (result != AV_ERR_OK) {
572 cout << "push input data failed,error:" << result << endl;
573 } else {
574 inputNum++;
575 }
576 return 0;
577 }
578
SendData(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)579 int32_t HDRCodecNdkSample::SendData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data)
580 {
581 switch (typeDec) {
582 case CHANNEL_0: {
583 return SendDataHdr(codec, index, data);
584 }
585 case CHANNEL_1: {
586 return SendDataH263(codec, index, data);
587 }
588 case CHANNEL_2: {
589 return SendDataAvc(codec, index, data);
590 }
591 case CHANNEL_3: {
592 return SendDataMpeg2(codec, index, data);
593 }
594 case CHANNEL_4: {
595 return SendDataMpeg4(codec, index, data);
596 }
597 default:
598 g_isRunning.store(false);
599 g_cv.notify_all();
600 return 1;
601 }
602 return 0;
603 }
604
RepeatCallStartFlush(HDRCodecNdkSample * sample)605 static int32_t RepeatCallStartFlush(HDRCodecNdkSample *sample)
606 {
607 int32_t ret = 0;
608 sample->REPEAT_START_FLUSH_BEFORE_EOS--;
609 ret = OH_VideoEncoder_Flush(sample->venc_);
610 if (ret != AV_ERR_OK) {
611 return ret;
612 }
613 ret = OH_VideoDecoder_Flush(sample->vdec_);
614 if (ret != AV_ERR_OK) {
615 return ret;
616 }
617 sample->FlushBuffer();
618 ret = OH_VideoEncoder_Start(sample->venc_);
619 if (ret != AV_ERR_OK) {
620 return ret;
621 }
622 ret = OH_VideoDecoder_Start(sample->vdec_);
623 if (ret != AV_ERR_OK) {
624 return ret;
625 }
626 return 0;
627 }
628
RepeatCallStartStop(HDRCodecNdkSample * sample)629 static int32_t RepeatCallStartStop(HDRCodecNdkSample *sample)
630 {
631 int32_t ret = 0;
632 sample->REPEAT_START_STOP_BEFORE_EOS--;
633 ret = OH_VideoDecoder_Stop(sample->vdec_);
634 if (ret != AV_ERR_OK) {
635 return ret;
636 }
637 ret = OH_VideoEncoder_Stop(sample->venc_);
638 if (ret != AV_ERR_OK) {
639 return ret;
640 }
641 sample->FlushBuffer();
642 ret = OH_VideoEncoder_Start(sample->venc_);
643 if (ret != AV_ERR_OK) {
644 return ret;
645 }
646 ret = OH_VideoDecoder_Start(sample->vdec_);
647 if (ret != AV_ERR_OK) {
648 return ret;
649 }
650 return 0;
651 }
652
RepeatCallStartFlushStop(HDRCodecNdkSample * sample)653 static int32_t RepeatCallStartFlushStop(HDRCodecNdkSample *sample)
654 {
655 int32_t ret = 0;
656 sample->REPEAT_START_FLUSH_STOP_BEFORE_EOS--;
657 ret = OH_VideoEncoder_Flush(sample->venc_);
658 if (ret != AV_ERR_OK) {
659 return ret;
660 }
661 ret = OH_VideoDecoder_Flush(sample->vdec_);
662 if (ret != AV_ERR_OK) {
663 return ret;
664 }
665 ret = OH_VideoDecoder_Stop(sample->vdec_);
666 if (ret != AV_ERR_OK) {
667 return ret;
668 }
669 ret = OH_VideoEncoder_Stop(sample->venc_);
670 if (ret != AV_ERR_OK) {
671 return ret;
672 }
673 sample->FlushBuffer();
674 ret = OH_VideoEncoder_Start(sample->venc_);
675 if (ret != AV_ERR_OK) {
676 return ret;
677 }
678 ret = OH_VideoDecoder_Start(sample->vdec_);
679 if (ret != AV_ERR_OK) {
680 return ret;
681 }
682 return 0;
683 }
684
~HDRCodecNdkSample()685 HDRCodecNdkSample::~HDRCodecNdkSample()
686 {
687 inputNum = 0;
688 Release();
689 }
690
CreateCodec()691 int32_t HDRCodecNdkSample::CreateCodec()
692 {
693 decSignal = new VSignal();
694 if (decSignal == nullptr) {
695 return AV_ERR_UNKNOWN;
696 }
697 vdec_ = OH_VideoDecoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
698 if (vdec_ == nullptr) {
699 return AV_ERR_UNKNOWN;
700 }
701
702 venc_ = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
703 if (venc_ == nullptr) {
704 return AV_ERR_UNKNOWN;
705 }
706 return AV_ERR_OK;
707 }
708
GetFileSize(const char * fileName)709 static int64_t GetFileSize(const char *fileName)
710 {
711 int64_t fileSize = 0;
712 if (fileName != nullptr) {
713 struct stat fileStatus {};
714 if (stat(fileName, &fileStatus) == 0) {
715 fileSize = static_cast<int64_t>(fileStatus.st_size);
716 }
717 }
718 return fileSize;
719 }
720
CreateDemuxerVideocoder(const char * file,std::string codeName,std::string enCodeName)721 int32_t HDRCodecNdkSample::CreateDemuxerVideocoder(const char *file, std::string codeName, std::string enCodeName)
722 {
723 int trackType = 0;
724 fd = open(file, O_RDONLY);
725 outFd = open("./output.mp4", O_CREAT | O_RDWR |O_TRUNC, S_IRUSR | S_IWUSR);
726 int64_t size = GetFileSize(file);
727 source = OH_AVSource_CreateWithFD(fd, 0, size);
728 if (!source) {
729 return AV_ERR_UNKNOWN;
730 }
731 if (CreateVideocoder(codeName, enCodeName)) {
732 return AV_ERR_UNKNOWN;
733 }
734 demuxer = OH_AVDemuxer_CreateWithSource(source);
735 muxer = OH_AVMuxer_Create(outFd, AV_OUTPUT_FORMAT_MPEG_4);
736 if (!demuxer || !muxer) {
737 return AV_ERR_UNKNOWN;
738 }
739 OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
740 OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount);
741 OH_AVMuxer_SetFormat(muxer, sourceFormat);
742 int32_t muxTrack = 0;
743 for (int32_t index = 0; index < trackCount; index++) {
744 OH_AVDemuxer_SelectTrackByID(demuxer, index);
745 OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
746 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType);
747 if (trackType == MEDIA_TYPE_VID) {
748 videoTrackID = index;
749 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_ROTATION, &DEFAULT_ROTATION);
750 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_WIDTH, &DEFAULT_WIDTH);
751 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_HEIGHT, &DEFAULT_HEIGHT);
752 OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_PIXEL_FORMAT, &DEFAULT_PIXEL_FORMAT);
753 OH_AVFormat_GetDoubleValue(trackFormat, OH_MD_KEY_FRAME_RATE, &DEFAULT_FRAME_RATE);
754 OH_AVFormat_SetStringValue(trackFormat, OH_MD_KEY_CODEC_MIME, MIME_TYPE);
755 OH_AVMuxer_SetRotation(muxer, DEFAULT_ROTATION);
756 } else {
757 audioTrackID = index;
758 }
759 OH_AVMuxer_AddTrack(muxer, &muxTrack, trackFormat);
760 OH_AVMuxer_SetFormat(muxer, trackFormat);
761 OH_AVFormat_Destroy(trackFormat);
762 trackFormat = nullptr;
763 }
764 return AV_ERR_OK;
765 }
766
CreateVideocoder(std::string codeName,std::string enCodeName)767 int32_t HDRCodecNdkSample::CreateVideocoder(std::string codeName, std::string enCodeName)
768 {
769 decSignal = new VSignal();
770 if (decSignal == nullptr) {
771 return AV_ERR_UNKNOWN;
772 }
773 vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
774 if (vdec_ == nullptr) {
775 return AV_ERR_UNKNOWN;
776 }
777
778 venc_ = OH_VideoEncoder_CreateByName(enCodeName.c_str());
779 if (venc_ == nullptr) {
780 return AV_ERR_UNKNOWN;
781 }
782 return AV_ERR_OK;
783 }
784
FlushBuffer()785 void HDRCodecNdkSample::FlushBuffer()
786 {
787 unique_lock<mutex> decInLock(decSignal->inMutex_);
788 clearIntqueue(decSignal->inIdxQueue_);
789 std::queue<OH_AVMemory *>empty;
790 swap(empty, decSignal->inBufferQueue_);
791 decSignal->inCond_.notify_all();
792 inFile_->clear();
793 inFile_->seekg(0, ios::beg);
794 decInLock.unlock();
795 }
796
RepeatCall()797 int32_t HDRCodecNdkSample::RepeatCall()
798 {
799 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
800 return RepeatCallStartFlush(this);
801 }
802 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
803 return RepeatCallStartStop(this);
804 }
805 if (REPEAT_START_FLUSH_STOP_BEFORE_EOS > 0) {
806 return RepeatCallStartFlushStop(this);
807 }
808 return 0;
809 }
810
InputFunc()811 void HDRCodecNdkSample::InputFunc()
812 {
813 while (true) {
814 if (!g_isRunning.load()) {
815 break;
816 }
817 int32_t ret = RepeatCall();
818 if (ret != 0) {
819 cout << "repeat call failed, errcode " << ret << endl;
820 errorCount++;
821 g_isRunning.store(false);
822 g_cv.notify_all();
823 break;
824 }
825 uint32_t index;
826 unique_lock<mutex> lock(decSignal->inMutex_);
827 decSignal->inCond_.wait(lock, [this]() {
828 if (!g_isRunning.load()) {
829 return true;
830 }
831 return decSignal->inIdxQueue_.size() > 0;
832 });
833 if (!g_isRunning.load()) {
834 break;
835 }
836 index = decSignal->inIdxQueue_.front();
837 auto buffer = decSignal->inBufferQueue_.front();
838
839 decSignal->inIdxQueue_.pop();
840 decSignal->inBufferQueue_.pop();
841 lock.unlock();
842 if (SendData(vdec_, index, buffer) == 1)
843 break;
844 }
845 }
846
Configure()847 int32_t HDRCodecNdkSample::Configure()
848 {
849 OH_AVFormat *format = OH_AVFormat_Create();
850 if (format == nullptr) {
851 cout << "Fatal: Failed to create format" << endl;
852 return AV_ERR_UNKNOWN;
853 }
854 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
855 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
856 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXEL_FORMAT);
857 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
858 int ret = OH_VideoDecoder_Configure(vdec_, format);
859 if (ret != AV_ERR_OK) {
860 return ret;
861 }
862 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, DEFAULT_PROFILE);
863 ret = OH_VideoEncoder_Configure(venc_, format);
864 if (ret != AV_ERR_OK) {
865 return ret;
866 }
867 ret = OH_VideoEncoder_GetSurface(venc_, &window);
868 if (ret != AV_ERR_OK) {
869 return ret;
870 }
871 ret = OH_VideoDecoder_SetSurface(vdec_, window);
872 if (ret != AV_ERR_OK) {
873 return ret;
874 }
875 encCb_.onError = VencError;
876 encCb_.onStreamChanged = VencFormatChanged;
877 encCb_.onNeedInputData = VencInputDataReady;
878 encCb_.onNeedOutputData = VencOutputDataReady;
879 ret = OH_VideoEncoder_SetCallback(venc_, encCb_, this);
880 if (ret != AV_ERR_OK) {
881 return ret;
882 }
883 OH_AVFormat_Destroy(format);
884 decCb_.onError = VdecError;
885 decCb_.onStreamChanged = VdecFormatChanged;
886 decCb_.onNeedInputData = VdecInputDataReady;
887 decCb_.onNeedOutputData = VdecOutputDataReady;
888 return OH_VideoDecoder_SetCallback(vdec_, decCb_, this);
889 }
890
ReConfigure()891 int32_t HDRCodecNdkSample::ReConfigure()
892 {
893 int32_t ret = OH_VideoDecoder_Reset(vdec_);
894 if (ret != AV_ERR_OK) {
895 return ret;
896 }
897 ret = OH_VideoEncoder_Reset(venc_);
898 if (ret != AV_ERR_OK) {
899 return ret;
900 }
901 FlushBuffer();
902 OH_AVFormat *format = OH_AVFormat_Create();
903 if (format == nullptr) {
904 cout<< "Fatal: Failed to create format" << endl;
905 return AV_ERR_UNKNOWN;
906 }
907 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
908 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
909 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXEL_FORMAT);
910 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
911 ret = OH_VideoDecoder_Configure(vdec_, format);
912 if (ret != AV_ERR_OK) {
913 OH_AVFormat_Destroy(format);
914 return ret;
915 }
916 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, DEFAULT_PROFILE);
917 ret = OH_VideoEncoder_Configure(venc_, format);
918 if (ret != AV_ERR_OK) {
919 OH_AVFormat_Destroy(format);
920 return ret;
921 }
922 ret = OH_VideoDecoder_SetSurface(vdec_, window);
923 if (ret != AV_ERR_OK) {
924 OH_AVFormat_Destroy(format);
925 return ret;
926 }
927 OH_AVFormat_Destroy(format);
928 return ret;
929 }
930
WriteAudioTrack()931 void HDRCodecNdkSample::WriteAudioTrack()
932 {
933 OH_AVMemory *buffer = nullptr;
934 buffer = OH_AVMemory_Create(AUDIO_BUFFER_SIZE);
935 bool audioWrite = true;
936 while (audioWrite) {
937 if (!g_isRunning.load()) {
938 audioWrite = false;
939 break;
940 }
941 OH_AVCodecBufferAttr info;
942 OH_AVDemuxer_ReadSample(demuxer, audioTrackID, buffer, &info);
943 if (info.flags & AVCODEC_BUFFER_FLAGS_EOS) {
944 audioWrite = false;
945 break;
946 }
947 OH_AVMuxer_WriteSample(muxer, audioTrackID, buffer, info);
948 }
949 OH_AVMemory_Destroy(buffer);
950 }
951
StartDemuxer()952 int32_t HDRCodecNdkSample::StartDemuxer()
953 {
954 int32_t ret = 0;
955 g_isRunning.store(true);
956 OH_AVMuxer_Start(muxer);
957 ret = OH_VideoEncoder_Start(venc_);
958 if (ret != AV_ERR_OK) {
959 return ret;
960 }
961 ret = OH_VideoDecoder_Start(vdec_);
962 if (ret != AV_ERR_OK) {
963 return ret;
964 }
965 if (audioTrackID != -1) {
966 audioThread = make_unique<thread>(&HDRCodecNdkSample::WriteAudioTrack, this);
967 }
968 return 0;
969 }
Start()970 int32_t HDRCodecNdkSample::Start()
971 {
972 int32_t ret = 0;
973 prereadBuffer_ = std::make_unique<uint8_t []>(PREREAD_BUFFER_SIZE + START_CODE_SIZE);
974 mpegUnit_ = std::make_unique<std::vector<uint8_t>>(MAX_NALU_SIZE);
975 inFile_ = make_unique<ifstream>();
976 inFile_->open(INP_DIR, ios::in | ios::binary);
977 if (!inFile_->is_open()) {
978 (void)OH_VideoDecoder_Destroy(vdec_);
979 (void)OH_VideoEncoder_Destroy(venc_);
980 vdec_ = nullptr;
981 venc_ = nullptr;
982 inFile_->close();
983 inFile_.reset();
984 inFile_ = nullptr;
985 return AV_ERR_UNKNOWN;
986 }
987 g_isRunning.store(true);
988 ret = OH_VideoEncoder_Start(venc_);
989 if (ret != AV_ERR_OK) {
990 return ret;
991 }
992 ret = OH_VideoDecoder_Start(vdec_);
993 if (ret != AV_ERR_OK) {
994 return ret;
995 }
996 inputLoop_ = make_unique<thread>(&HDRCodecNdkSample::InputFunc, this);
997 if (inputLoop_ == nullptr) {
998 g_isRunning.store(false);
999 (void)OH_VideoDecoder_Stop(vdec_);
1000 ReleaseInFile();
1001 return AV_ERR_UNKNOWN;
1002 }
1003
1004 return 0;
1005 }
1006
StopInloop()1007 void HDRCodecNdkSample::StopInloop()
1008 {
1009 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
1010 unique_lock<mutex> lock(decSignal->inMutex_);
1011 clearIntqueue(decSignal->inIdxQueue_);
1012 g_isRunning.store(false);
1013 decSignal->inCond_.notify_all();
1014 lock.unlock();
1015 inputLoop_->join();
1016 inputLoop_.reset();
1017 }
1018 }
1019
ReleaseInFile()1020 void HDRCodecNdkSample::ReleaseInFile()
1021 {
1022 if (inFile_ != nullptr) {
1023 if (inFile_->is_open()) {
1024 inFile_->close();
1025 }
1026 inFile_.reset();
1027 inFile_ = nullptr;
1028 }
1029 }
1030
WaitForEos()1031 void HDRCodecNdkSample::WaitForEos()
1032 {
1033 std::mutex mtx;
1034 unique_lock<mutex> lock(mtx);
1035 g_cv.wait(lock, []() {
1036 return !(g_isRunning.load());
1037 });
1038 if (audioThread) {
1039 audioThread->join();
1040 }
1041 if (inputLoop_) {
1042 inputLoop_->join();
1043 }
1044 OH_VideoDecoder_Stop(vdec_);
1045 OH_VideoEncoder_Stop(venc_);
1046 }
1047
Release()1048 int32_t HDRCodecNdkSample::Release()
1049 {
1050 if (decSignal != nullptr) {
1051 delete decSignal;
1052 decSignal = nullptr;
1053 }
1054 if (vdec_ != nullptr) {
1055 OH_VideoDecoder_Destroy(vdec_);
1056 vdec_ = nullptr;
1057 }
1058 if (venc_ != nullptr) {
1059 OH_VideoEncoder_Destroy(venc_);
1060 venc_ = nullptr;
1061 }
1062 if (muxer != nullptr) {
1063 OH_AVMuxer_Destroy(muxer);
1064 muxer = nullptr;
1065 }
1066 if (demuxer != nullptr) {
1067 OH_AVDemuxer_Destroy(demuxer);
1068 demuxer = nullptr;
1069 }
1070 if (source != nullptr) {
1071 OH_AVSource_Destroy(source);
1072 source = nullptr;
1073 }
1074 if (fd > 0) {
1075 close(fd);
1076 fd = -1;
1077 }
1078 if (outFd > 0) {
1079 close(outFd);
1080 outFd = -1;
1081 }
1082 return 0;
1083 }