1 /*
2 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development 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 "audio_pcm_processor.h"
17 #include "const_def.h"
18 #include "sharing_log.h"
19
20 namespace OHOS {
21 namespace Sharing {
22 constexpr uint32_t LPCM_PES_PAYLOAD_PRIVATE_SIZE = 4;
23 constexpr uint32_t LPCM_PES_PAYLOAD_DATA_SIZE = 1920;
24 constexpr uint32_t LPCM_PES_PAYLOAD_TIME_DURATION = 10;
25 constexpr uint32_t FIFO_SAMPLES = 3840;
26 constexpr uint8_t AUDIO_SAMPLING_FREQUENCY_48K = 2 << 3;
27 constexpr uint8_t NUMBER_OF_AUDIO_CHANNEL_STEREO = 1;
28
29 static std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
30 static uint64_t duration = 0;
31 static uint8_t data[LPCM_PES_PAYLOAD_DATA_SIZE];
32
AudioPcmProcessor()33 AudioPcmProcessor::AudioPcmProcessor()
34 {
35 SHARING_LOGD("trace.");
36 }
37
~AudioPcmProcessor()38 AudioPcmProcessor::~AudioPcmProcessor()
39 {
40 av_audio_fifo_free(fifo_);
41 SHARING_LOGD("trace.");
42 }
43
Init(uint32_t channels,uint32_t sampleBit,uint32_t sampleRate)44 int32_t AudioPcmProcessor::Init(uint32_t channels, uint32_t sampleBit, uint32_t sampleRate)
45 {
46 channels_ = channels;
47 sampleBit_ = sampleBit;
48 sampleRate_ = sampleRate;
49 if (channels_ == 0 || sampleBit_ == 0 || sampleRate_ == 0) {
50 SHARING_LOGE("Invalid pcm parameters!");
51 return 1;
52 }
53
54 sampleSize_ = sampleBit * channels / AUDIO_SAMPLE_BIT_U8;
55 if (!(fifo_ = av_audio_fifo_alloc(AV_SAMPLE_FMT_S16, channels, FIFO_SAMPLES))) {
56 SHARING_LOGE("Could not allocate FIFO");
57 return 1;
58 }
59 return 0;
60 }
61
OnFrame(const Frame::Ptr & frame)62 void AudioPcmProcessor::OnFrame(const Frame::Ptr &frame)
63 {
64 if (frame == nullptr) {
65 SHARING_LOGE("frame is nullptr!");
66 return;
67 }
68
69 if (channels_ == 0 || sampleBit_ == 0 || sampleRate_ == 0) {
70 SHARING_LOGE("Invalid pcm parameters!");
71 return;
72 }
73
74 if (duration == 0) {
75 std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
76 duration = (uint64_t)std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
77 }
78
79 PcmLittleToBigEndian(frame->Data(), frame->Size());
80 uint8_t *captureData[] = {frame->Data()};
81 uint8_t *payloadData[] = {data};
82 if (sampleSize_ == 0) {
83 return;
84 }
85 int32_t payloadSampleNum = (int32_t)(LPCM_PES_PAYLOAD_DATA_SIZE / sampleSize_);
86 av_audio_fifo_write(fifo_, reinterpret_cast<void **>(captureData), frame->Size() / sampleSize_);
87 while (av_audio_fifo_size(fifo_) >= payloadSampleNum) {
88 av_audio_fifo_read(fifo_, reinterpret_cast<void **>(payloadData), payloadSampleNum);
89 auto pcmFrame = FrameImpl::Create();
90 if (pcmFrame == nullptr) {
91 continue;
92 }
93 pcmFrame->pts_ = duration;
94 pcmFrame->codecId_ = CODEC_PCM;
95 pcmFrame->SetCapacity(LPCM_PES_PAYLOAD_PRIVATE_SIZE + LPCM_PES_PAYLOAD_DATA_SIZE);
96 pcmFrame->Append(0xa0); // 0xa0 - sub_stream_id
97 pcmFrame->Append(0x06); // 0x06 - number_of_frame_header
98 pcmFrame->Append(0x00); // audio_emphasis_flag
99 pcmFrame->Append(AUDIO_SAMPLING_FREQUENCY_48K | NUMBER_OF_AUDIO_CHANNEL_STEREO);
100 pcmFrame->Append(payloadData[0], LPCM_PES_PAYLOAD_DATA_SIZE);
101 DeliverFrame(pcmFrame);
102 duration += LPCM_PES_PAYLOAD_TIME_DURATION;
103 }
104 }
105
PcmLittleToBigEndian(uint8_t * data,int32_t size)106 void AudioPcmProcessor::PcmLittleToBigEndian(uint8_t *data, int32_t size)
107 {
108 if (channels_ == 0) {
109 return;
110 }
111 int32_t sampleSize = (int32_t)(sampleSize_ / channels_);
112 if (sampleSize <= 1) {
113 return;
114 }
115
116 uint8_t tmpData;
117 if (sampleSize != 0) {
118 int32_t count = size / sampleSize;
119 for (int32_t i = 0; i < count; i++) {
120 tmpData = data[i * sampleSize];
121 data[i * sampleSize] = data[i * sampleSize + 1];
122 data[i * sampleSize + 1] = tmpData;
123 }
124 }
125 }
126 } // namespace Sharing
127 } // namespace OHOS
128