• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <arpa/inet.h>
17 #include <functional>
18 #include <getopt.h>
19 #include <netinet/in.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 #include "rtp_def.h"
27 #include "rtp_factory.h"
28 
29 using namespace OHOS::Sharing;
30 
31 int gType = -1; // 0 for aac, 1 for h264, 2 for g711, 3 for mpegts
32 char *gFileName = nullptr;
33 char *gAudioFileName = nullptr;
34 int gPort = 1234;
35 FILE *gFd = nullptr;
36 FILE *gAudioFd = nullptr;
37 
38 #define BUFF_SIZE 10240
39 
ShowUsage(char * exe)40 void ShowUsage(char *exe)
41 {
42     printf("Usage:\n%s -t <type> -p <listening port> -o <file to save data>\n", exe);
43     printf("\t-t 0: AAC, 1: H264, 2: G711, 3: mpegts\n");
44     printf("\t-p local listening port, default 1234\n");
45     printf("\t-o file to save data OR video data in ts/ps demux stream, such as 123.h264, 234.aac\n");
46     printf("\t-a file to save audio data in ts/ps demux stream, such as 234.aac\n");
47 }
48 
ParseParam(int argc,char * argv[])49 int ParseParam(int argc, char *argv[])
50 {
51     int ret;
52     while ((ret = getopt(argc, argv, ":t:p:o:a:")) != -1) {
53         switch (ret) {
54             case ('t'):
55                 gType = atoi(optarg);
56                 break;
57             case ('p'):
58                 gPort = atoi(optarg);
59                 break;
60             case ('o'):
61                 gFileName = optarg;
62                 break;
63             case ('a'):
64                 gAudioFileName = optarg;
65                 break;
66             case ':':
67                 printf("option [-%c] requires an argument", static_cast<char>(optopt));
68                 break;
69             case '?':
70                 printf("unknown option: %c", static_cast<char>(optopt));
71                 break;
72             default:
73                 break;
74         }
75     }
76 
77     if ((gType < 0 || gType > 3) || gFileName == nullptr) {
78         printf("param error\n");
79         ShowUsage(argv[0]);
80         return -1;
81     }
82     return 0;
83 }
84 
RecvUDP(const std::function<void (const char * buf,int len)> & cb)85 int RecvUDP(const std::function<void(const char *buf, int len)> &cb)
86 {
87     int servSocket, nbytes;
88     struct sockaddr_in servAddr, cliAddr;
89     int addrLen = sizeof(cliAddr);
90     char buffer[BUFF_SIZE];
91 
92     if ((servSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
93         perror("socket err");
94         return -1;
95     }
96 
97     bzero(&servAddr, sizeof(servAddr));
98 
99     servAddr.sin_family = AF_INET;
100     servAddr.sin_port = htons(gPort);
101     servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
102 
103     if (bind(servSocket, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
104         perror("bind err");
105         return -1;
106     }
107 
108     while (1) {
109         if ((nbytes = recvfrom(servSocket, buffer, sizeof(buffer), 0, (struct sockaddr *)&cliAddr,
110                                (socklen_t *)&addrLen)) < 0) {
111             perror("recvfrom err");
112             return -1;
113         }
114 
115         printf("\nRecv data(size:%d) From %s:%d\n", nbytes, inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port));
116 
117         cb(buffer, nbytes);
118         memset(buffer, 0, BUFF_SIZE);
119     }
120 }
121 
HandleSignal(int sig)122 void HandleSignal(int sig)
123 {
124     if (gFd != nullptr) {
125         fclose(gFd);
126     }
127 
128     if (gAudioFd != nullptr) {
129         fclose(gAudioFd);
130     }
131     printf("Catch Ctrl+C,\nsave '%s' success\nexit success.\n", gFileName);
132     exit(0);
133 }
134 
main(int argc,char * argv[])135 int main(int argc, char *argv[])
136 {
137     if (ParseParam(argc, argv) != 0) {
138         return -1;
139     }
140     printf("%s -t %d -p %d -o %s -a %s\n", argv[0], gType, gPort, gFileName, gAudioFileName);
141 
142     // Catch Ctrl+C signal
143     signal(SIGINT, HandleSignal);
144     if (gFileName != nullptr) {
145         gFd = fopen(gFileName, "wb");
146     }
147     if (gAudioFileName) {
148         gAudioFd = fopen(gAudioFileName, "wb");
149     }
150     if (gType == 1) {
151         auto h264unPack = RtpFactory::CreateRtpUnpack(RtpPlaylodParam{96, 90000, RtpPayloadStream::H264});
152         h264unPack->SetOnRtpUnpack([=](uint32_t ssrc, const Frame::Ptr &frame) {
153             if (frame->GetTrackType() == TRACK_VIDEO) {
154                 printf("h264 data: len: %d dts: %d\n", frame->Size(), frame->Dts());
155                 auto data = frame->Data();
156                 auto bytes = frame->Size();
157                 for (size_t i = 0; i < 16 && i < bytes; i++) {
158                     printf("%02x ", data[i] & 0xff);
159                 }
160                 printf("\n");
161                 fwrite(frame->Data(), frame->Size(), 1, gFd); // save .h264 file
162             }
163         });
164 
165         RecvUDP([h264unPack](const char *buf, int len) {
166             // print data (12B RTP header + 12B Payload)
167             for (size_t i = 0; i < 24 && i < len; i++) {
168                 printf("%02x ", buf[i] & 0xff);
169                 if (i == 11) {
170                     printf("\n");
171                 }
172             }
173             printf("\n");
174             h264unPack->ParseRtp(buf, len);
175         });
176 
177     } else if (gType == 0) {
178         auto extra = std::make_shared<AACExtra>();
179         extra->aacConfig_ = "1210";
180         auto aacunPack =
181             RtpFactory::CreateRtpUnpack(RtpPlaylodParam{97, 44100, RtpPayloadStream::MPEG4_GENERIC, extra});
182         aacunPack->SetOnRtpUnpack([=](uint32_t ssrc, const Frame::Ptr &frame) {
183             printf("SetOnRtpUnpack\n");
184             if (frame->GetTrackType() == TRACK_AUDIO) {
185                 printf("aac data: len: %d dts: %d\n", frame->Size(), frame->Dts());
186                 auto data = frame->Data();
187                 auto bytes = frame->Size();
188                 for (size_t i = 0; i < 16 && i < bytes; i++) {
189                     printf("%02x ", data[i] & 0xff);
190                 }
191                 printf("\n");
192                 fwrite(frame->Data(), frame->Size(), 1, gFd); // save .aac file
193             }
194         });
195 
196         RecvUDP([aacunPack](const char *buf, int len) {
197             // print data (12B RTP header + 12B Payload)
198             for (size_t i = 0; i < 24 && i < len; i++) {
199                 printf("%02x ", buf[i] & 0xff);
200                 if (i == 11) {
201                     printf("\n");
202                 }
203             }
204             printf("\n");
205             aacunPack->ParseRtp(buf, len);
206         });
207     } else if (gType == 2) {
208         auto g711Unpack = RtpFactory::CreateRtpUnpack(RtpPlaylodParam{97, 8000, RtpPayloadStream::PCMA});
209         g711Unpack->SetOnRtpUnpack([=](uint32_t ssrc, const Frame::Ptr &frame) {
210             printf("SetOnRtpUnpack\n");
211             if (frame->GetTrackType() == TRACK_AUDIO) {
212                 printf("g711 data: len: %d dts: %d\n", frame->Size(), frame->Dts());
213                 auto data = frame->Data();
214                 auto bytes = frame->Size();
215                 for (size_t i = 0; i < 16 && i < bytes; i++) {
216                     printf("%02x ", data[i] & 0xff);
217                 }
218                 printf("\n");
219                 fwrite(frame->Data(), frame->Size(), 1, gFd); // save .pcma file
220             }
221         });
222 
223         RecvUDP([g711Unpack](const char *buf, int len) {
224             // print data (12B RTP header + 12B Payload)
225             for (size_t i = 0; i < 24 && i < len; i++) {
226                 printf("%02x ", buf[i] & 0xff);
227                 if (i == 11) {
228                     printf("\n");
229                 }
230             }
231             printf("\n");
232             g711Unpack->ParseRtp(buf, len);
233         });
234     } else if (gType == 3) {
235         auto tsUnpack = RtpFactory::CreateRtpUnpack(RtpPlaylodParam{33, 90000, RtpPayloadStream::MPEG2_TS});
236         tsUnpack->SetOnRtpUnpack([=](uint32_t ssrc, const Frame::Ptr &frame) {
237             printf("mpegts OnRtpUnpack in TrackType = %d size=%d dts=%d\n", frame->GetTrackType(), frame->Size(),
238                    frame->Dts());
239             printf("ts data: len: %d dts: %d\n", frame->Size(), frame->Dts());
240             auto data = frame->Data();
241             auto bytes = frame->Size();
242             for (size_t i = 0; i < 16 && i < bytes; i++) {
243                 printf("%02x ", data[i] & 0xff);
244             }
245             printf("\n");
246             if (frame->GetTrackType() == TRACK_VIDEO) {
247                 fwrite(frame->Data(), frame->Size(), 1, gFd); // save .h264 file
248             } else if (frame->GetTrackType() == TRACK_AUDIO) {
249                 fwrite(frame->Data(), frame->Size(), 1, gAudioFd);
250             }
251         });
252 
253         RecvUDP([tsUnpack](const char *buf, int len) {
254             // print data (12B RTP header + 12B Payload)
255             for (size_t i = 0; i < 24 && i < len; i++) {
256                 printf("%02x ", buf[i] & 0xff);
257                 if (i == 11) {
258                     printf("\n");
259                 }
260             }
261             printf("\n");
262             tsUnpack->ParseRtp(buf, len);
263         });
264     }
265 
266     return 0;
267 }