1 /*
2  * Copyright (c) 2023 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 <fstream>
17 #include <functional>
18 #include <getopt.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include "codec_factory.h"
24 #include "common/sharing_log.h"
25 #include "frame.h"
26 #include "media_frame_pipeline.h"
27 
28 using namespace OHOS::Sharing;
29 
30 char *gInFile = nullptr;
31 char *gOutFile = nullptr;
32 int gType = -1; // 0 for decode, 1 for encode
33 
ShowUsage(char *exe)34 void ShowUsage(char *exe)
35 {
36     SHARING_LOGD("usage:\n%{public}s -t <type> -i <in file> -o <out file>", exe);
37     SHARING_LOGD("\t-t 0: decode G.711, 1: encode G.711, 2:decode AAC-ADTS");
38     SHARING_LOGD("\t-i in file");
39     SHARING_LOGD("\t-o out file");
40 }
41 
ParseParam(int argc, char *argv[])42 int ParseParam(int argc, char *argv[])
43 {
44     int ret;
45 
46     while ((ret = getopt(argc, argv, ":t:i:o:")) != -1) {
47         switch (ret) {
48             case ('t'):
49                 gType = atoi(optarg);
50                 break;
51             case ('i'):
52                 gInFile = optarg;
53                 break;
54             case ('o'):
55                 gOutFile = optarg;
56                 break;
57             case ':':
58                 SHARING_LOGD("option [-%c] requires an argument.", static_cast<char>(optopt));
59                 break;
60             case '?':
61                 SHARING_LOGD("unknown option: %c.", static_cast<char>(optopt));
62                 break;
63             default:
64                 break;
65         }
66     }
67 
68     if ((gType > 2 || gType < 0) || gInFile == nullptr || gOutFile == nullptr) {
69         SHARING_LOGD("param error");
70         ShowUsage(argv[0]);
71         return -1;
72     }
73 
74     return 0;
75 }
76 
77 class RawDataReceiver : public FrameDestination {
78 public:
RawDataReceiver(std::fstream &fd)79     RawDataReceiver(std::fstream &fd) : fd_(fd) {}
80     ~RawDataReceiver() = default;
81     void OnFrame(const Frame::Ptr &frame) override
82     {
83         fd_.write((char *)frame->Data(), frame->Size());
84         SHARING_LOGD("write data(%{public}p) len(%{public}d)", frame->Data(), frame->Size());
85     }
86 
87 private:
88     std::fstream &fd_;
89 };
90 
DecodeG711(char *data, int length, std::fstream &fd)91 void DecodeG711(char *data, int length, std::fstream &fd)
92 {
93     std::shared_ptr<AudioDecoder> decoder = CodecFactory::CreateAudioDecoder(CODEC_G711A);
94     if (!decoder) {
95         return;
96     }
97     decoder->Init();
98 
99     auto rawReceiver = std::make_shared<RawDataReceiver>(fd);
100 
101     decoder->AddAudioDestination(rawReceiver);
102     auto g711Frame = FrameImpl::Create();
103     g711Frame->codecId_ = CODEC_G711A;
104     char *p = data;
105     for (int i = 0; i < length / 160; i++) {
106         SHARING_LOGD("for i(%{public}d)", i);
107         g711Frame->Clear();
108         g711Frame->Assign(p, 160);
109         decoder->OnFrame(g711Frame);
110         p += 160;
111     }
112     SHARING_LOGD("decodeG711 line(%{public}d).", __LINE__);
113 }
114 
DecodeAAC(char *data, int length, std::fstream &fd)115 void DecodeAAC(char *data, int length, std::fstream &fd)
116 {
117     std::shared_ptr<AudioDecoder> decoder = CodecFactory::CreateAudioDecoder(OHOS::Sharing::CODEC_AAC);
118     if (!decoder) {
119         return;
120     }
121     decoder->Init();
122 
123     auto rawReceiver = std::make_shared<RawDataReceiver>(fd);
124 
125     decoder->AddAudioDestination(rawReceiver);
126     auto aacFrame = FrameImpl::Create();
127     aacFrame->codecId_ = CODEC_AAC;
128     char *p = data;
129     for (int i = 0; i < length / 2048; i++) {
130         SHARING_LOGD("for i(%{public}d)", i);
131         aacFrame->Clear();
132         aacFrame->Assign(p, 2048);
133         decoder->OnFrame(aacFrame);
134         p += 2048;
135     }
136     SHARING_LOGD("decodeAAC line(%{public}d).", __LINE__);
137 }
138 
EncodeG711(char *data, int length, std::fstream &fd)139 void EncodeG711(char *data, int length, std::fstream &fd)
140 {
141     std::shared_ptr<AudioEncoder> encoder = CodecFactory::CreateAudioEncoder(CODEC_G711A);
142     if (!encoder) {
143         return;
144     }
145     encoder->Init();
146 
147     auto rawReceiver = std::make_shared<RawDataReceiver>(fd);
148 
149     encoder->AddAudioDestination(rawReceiver);
150 
151     auto pcmFrame = FrameImpl::Create();
152     pcmFrame->codecId_ = CODEC_PCM;
153     char *p = data;
154     for (int i = 0; i < length / 320; i++) {
155         SHARING_LOGD("for i(%{public}d)", i);
156         pcmFrame->Clear();
157         pcmFrame->Assign(p, 320);
158         encoder->OnFrame(pcmFrame);
159         p += 320;
160     }
161     SHARING_LOGD("decodeG711 line(%{public}d).", __LINE__);
162 }
163 
main(int argc, char *argv[])164 int main(int argc, char *argv[])
165 {
166     SHARING_LOGD("hello codec_demo.");
167     if (ParseParam(argc, argv) != 0) {
168         return -1;
169     }
170 
171     std::fstream infile(gInFile, std::ios::in | std::ios_base::binary);
172     if (!infile.is_open()) {
173         SHARING_LOGD("failed to open file");
174         return -1;
175     }
176 
177     std::fstream outfile(gOutFile, std::ios::out | std::ios_base::binary);
178     if (!outfile.is_open()) {
179         SHARING_LOGD("failed to open file");
180         return -1;
181     }
182 
183     infile.seekg(0, std::ios::end);
184     int size = infile.tellg();
185     infile.seekg(0, std::ios::beg);
186 
187     char *content = new char[size];
188     infile.read(content, size);
189     SHARING_LOGD("size %{public}d.", size);
190     infile.close();
191     if (gType == 0) {
192         DecodeG711(content, size, outfile);
193     } else if (gType == 1) {
194         EncodeG711(content, size, outfile);
195     } else if (gType == 2) {
196         DecodeAAC(content, size, outfile);
197     }
198 
199     outfile.close();
200     delete[] content;
201 }
202