blob: 85ec0930d68e24ef7bdfeda23a4f00c0e51e0a26 [file] [log] [blame]
Gong Kefa504d72023-04-18 10:23:35 +08001#include <stdio.h>
2#include <string.h>
3#include "ts_indexer.h"
Yahui Hanad79ebb2023-07-19 17:02:21 +08004#include "bitstrm.h"
Gong Kefa504d72023-04-18 10:23:35 +08005
6#define TS_PKT_SIZE (188)
7
8//#define TS_INDEXER_DEBUG
9#ifdef TS_INDEXER_DEBUG
10#define INF(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
11#else
12#define INF(fmt, ...)
13#endif
14
15#define ERR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
16
Yahui Hana082ab62023-07-14 14:41:39 +080017#define NAL_TYPE_NON_IDR 1 // 非 IDR NALU 类型
18#define NAL_TYPE_IDR 5 // IDR NALU 类型
Gong Kefa504d72023-04-18 10:23:35 +080019
Yahui Han63de7082023-07-12 18:30:10 +080020#define HEVC_NALU_BLA_W_LP 16
21#define HEVC_NALU_BLA_W_RADL 17
Yahui Hana082ab62023-07-14 14:41:39 +080022#define HEVC_NALU_BLA_N_LP 18
Yahui Han63de7082023-07-12 18:30:10 +080023#define HEVC_NALU_IDR_W_RADL 19
24#define HEVC_NALU_IDR_N_LP 20
25#define HEVC_NALU_TRAIL_CRA 21
26#define HEVC_NALU_SPS 33
27#define HEVC_NALU_AUD 35
28
Gong Kefa504d72023-04-18 10:23:35 +080029/**
30 * Initialize the TS indexer.
31 * \param ts_indexer The TS indexer to be initialized.
32 * \retval 0 On success.
33 * \retval -1 On error.
34 */
35int
36ts_indexer_init (TS_Indexer_t *ts_indexer)
37{
38 TSParser init_parser;
39
40 if (ts_indexer == NULL) {
41 return -1;
42 }
43
44 memset(&init_parser, 0, sizeof(TSParser));
45 init_parser.pid = 0x1fff;
46 init_parser.format = -1;
47 init_parser.PES.pts = -1;
48 init_parser.PES.offset = 0;
49 init_parser.PES.len = 0;
50 init_parser.PES.state = TS_INDEXER_STATE_INIT;
51
52 memcpy(&ts_indexer->video_parser, &init_parser, sizeof(TSParser));
53 memcpy(&ts_indexer->audio_parser, &init_parser, sizeof(TSParser));
54 ts_indexer->callback = NULL;
55 ts_indexer->offset = 0;
56
57 return 0;
58}
59
60/**
61 * Release the TS indexer.
62 * \param ts_indexer The TS indexer to be released.
63 */
64void
65ts_indexer_destroy (TS_Indexer_t *ts_indexer)
66{
67 return;
68}
69
70/**
71 * Set the video format.
72 * \param ts_indexer The TS indexer.
73 * \param format The stream format.
74 * \retval 0 On success.
75 * \retval -1 On error.
76 */
77int
78ts_indexer_set_video_format (TS_Indexer_t *ts_indexer, TS_Indexer_StreamFormat_t format)
79{
80 if (ts_indexer == NULL)
81 return -1;
82
83 ts_indexer->video_parser.format = format;
84
85 return 0;
86}
87
88/**
89 * Set the video PID.
90 * \param ts_indexer The TS indexer.
91 * \param pid The video PID.
92 * \retval 0 On success.
93 * \retval -1 On error.
94 */
95int
96ts_indexer_set_video_pid (TS_Indexer_t *ts_indexer, int pid)
97{
98 if (ts_indexer == NULL)
99 return -1;
100
101
102 TSParser *parser = &ts_indexer->video_parser;
103 parser->pid = pid;
104 parser->offset = 0;
105 parser->PES.pts = -1;
106 parser->PES.offset = 0;
107 parser->PES.len = 0;
108 parser->PES.state = TS_INDEXER_STATE_INIT;
109
110 return 0;
111}
112
113/**
114 * Set the audio PID.
115 * \param ts_indexer The TS indexer.
116 * \param pid The audio PID.
117 * \retval 0 On success.
118 * \retval -1 On error.
119 */
120int
121ts_indexer_set_audio_pid (TS_Indexer_t *ts_indexer, int pid)
122{
123 if (ts_indexer == NULL)
124 return -1;
125
126 TSParser *parser = &ts_indexer->audio_parser;
127 parser->pid = pid;
128 parser->offset = 0;
129 parser->PES.pts = -1;
130 parser->PES.offset = 0;
131 parser->PES.len = 0;
132 parser->PES.state = TS_INDEXER_STATE_INIT;
133
134 return 0;
135}
136
137/**
138 * Set the event callback function.
139 * \param ts_indexer The TS indexer.
140 * \param callback The event callback function.
141 * \retval 0 On success.
142 * \retval -1 On error.
143 */
144int
145ts_indexer_set_event_callback (TS_Indexer_t *ts_indexer, TS_Indexer_EventCallback_t callback)
146{
147 ts_indexer->callback = callback;
148
149 return 0;
150}
151
152static void find_mpeg(uint8_t *data, int len, TS_Indexer_t *indexer, TSParser *stream)
153{
154 int i;
155 uint32_t needle = 0;
Yahui Han63de7082023-07-12 18:30:10 +0800156 uint32_t needle1 = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800157 uint8_t *haystack = data;
158 int haystack_len = len;
159 int left = len;
160 // start code of picture header
161 uint8_t arr[4] = {0x00, 0x00, 0x01, 0x00};
Yahui Han63de7082023-07-12 18:30:10 +0800162 // start code of sequence header
163 uint8_t arr1[4] = {0x00, 0x00, 0x01, 0xb3};
Gong Kefa504d72023-04-18 10:23:35 +0800164 TS_Indexer_Event_t event;
165
166 /* mpeg header needs at least 4 bytes */
167 if (left < 4) {
168 memcpy(&stream->PES.data[0], &haystack, left);
169 stream->PES.len = left;
170 return;
171 }
172
173 memset(&event, 0, sizeof(event));
174 event.pid = stream->pid;
175 event.offset = stream->offset;
176
177 for (i = 0; i < 4; ++i) {
178 needle += (arr[i] << (8 * i));
179 }
180
Yahui Han63de7082023-07-12 18:30:10 +0800181 for (i = 0; i < 4; ++i) {
182 needle1 += (arr1[i] << (8 * i));
183 }
184
Gong Kefa504d72023-04-18 10:23:35 +0800185 for (i = 0; i < haystack_len - sizeof(needle) + 1;) {
Yahui Han63de7082023-07-12 18:30:10 +0800186 if (left < 5) {
187 INF("MPEG2 picture header across TS Packet\n");
188
189 /* MEPG2 picture header across TS packet, should cache the left data */
190 memcpy(&stream->PES.data[0], haystack + i, left);
191 stream->PES.len = left;
192 return;
193 }
194
Gong Kefa504d72023-04-18 10:23:35 +0800195 if (*(uint32_t *)(haystack + i) == needle) {
196 // picture header found
Yahui Han63de7082023-07-12 18:30:10 +0800197 int frame_type = (haystack[i + 5] >> 3) & 0x7;
198 switch (frame_type) {
199 case 1:
200 INF("I frame found, offset: %lx\n", event.offset);
201 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_I_FRAME;
202 break;
Gong Kefa504d72023-04-18 10:23:35 +0800203
Yahui Han63de7082023-07-12 18:30:10 +0800204 case 2:
205 INF("P frame found, offset: %lx\n", event.offset);
206 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_P_FRAME;
207 break;
208
209 case 3:
210 INF("B frame found, offset: %lx\n", event.offset);
211 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_B_FRAME;
212 break;
213
214 default:
215 i += 5;
216 left -= 5;
217 continue;
218
Gong Kefa504d72023-04-18 10:23:35 +0800219 }
220
Yahui Han63de7082023-07-12 18:30:10 +0800221 event.pts = stream->PES.pts;
222 if (indexer->callback) {
223 indexer->callback(indexer, &event);
224 }
225
226 i += 5;
227 left -= 5;
228 } else if (*(uint32_t *)(haystack + i) == needle1) {
229 // sequence header found
230 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_SEQUENCE;
231 event.pts = stream->PES.pts;
232 if (indexer->callback) {
233 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800234 }
235
236 i += 5;
237 left -= 5;
238 } else {
239 i ++;
240 left --;
241 }
242 }
243
244 if (left > 0) {
245 memcpy(&stream->PES.data[0], &haystack[i], left);
246 stream->PES.len = left;
247 } else {
248 stream->PES.len = 0;
249 }
250}
251
Yahui Hana082ab62023-07-14 14:41:39 +0800252static uint8_t *get_nalu(uint8_t *data, size_t len, size_t *nalu_len, uint8_t is_hevc)
Gong Kefa504d72023-04-18 10:23:35 +0800253{
Yahui Hana082ab62023-07-14 14:41:39 +0800254 size_t i = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800255 uint8_t *p = data;
256
257 if (len == 0)
258 return NULL;
259
260 //INF("%s enter, len:%#lx\n", __func__, len);
Yahui Han53b3c502023-08-04 10:36:58 +0800261 while (i < len - 4) {
262 if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01) {
Gong Kefa504d72023-04-18 10:23:35 +0800263 uint8_t *frame_data = data + i;
264 size_t frame_data_len = 0;
265
Yahui Hana082ab62023-07-14 14:41:39 +0800266 i += 4;
Gong Kefa504d72023-04-18 10:23:35 +0800267 //INF("%s start code prefix\n", __func__);
Yahui Han53b3c502023-08-04 10:36:58 +0800268 for (size_t j = i ; j < len - 4; ++j) {
269 if (p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x01) {
Gong Kefa504d72023-04-18 10:23:35 +0800270 frame_data_len = j - i;
271 break;
272 }
273 }
274
275 if (frame_data_len > 0) {
276 *nalu_len = frame_data_len;
277 return frame_data;
278 } else {
279 frame_data_len = len - i;
280 *nalu_len = frame_data_len;
281 return frame_data;
282 }
Yahui Hana082ab62023-07-14 14:41:39 +0800283 } else {
284 i ++;
Gong Kefa504d72023-04-18 10:23:35 +0800285 }
286 }
287
288 return NULL;
289}
290
Yahui Han114ba4f2023-07-19 14:07:01 +0800291uint32_t golomb_uev(uint32_t *pu4_bitstrm_ofst, uint32_t *pu4_bitstrm_buf)
Yahui Hana082ab62023-07-14 14:41:39 +0800292{
Yahui Hanad79ebb2023-07-19 17:02:21 +0800293 uint32_t u4_bitstream_offset = *pu4_bitstrm_ofst;
294 uint32_t u4_word, u4_ldz;
Yahui Hana082ab62023-07-14 14:41:39 +0800295
Yahui Hanad79ebb2023-07-19 17:02:21 +0800296 /* Find leading zeros in next 32 bits */
297 NEXTBITS_32(u4_word, u4_bitstream_offset, pu4_bitstrm_buf);
298 u4_ldz = CLZ(u4_word);
299 //printf("u4_ldz: %d, u4_word: %#x, offset: %d, pu4_bitstrm_buf: %#x\n",
300 // u4_ldz, u4_word, u4_bitstream_offset, *pu4_bitstrm_buf);
Yahui Hana082ab62023-07-14 14:41:39 +0800301
Yahui Hanad79ebb2023-07-19 17:02:21 +0800302 /* Flush the ps_bitstrm */
303 u4_bitstream_offset += (u4_ldz + 1);
Yahui Han114ba4f2023-07-19 14:07:01 +0800304
Yahui Hanad79ebb2023-07-19 17:02:21 +0800305 /* Read the suffix from the ps_bitstrm */
306 u4_word = 0;
307 if (u4_ldz)
308 GETBITS(u4_word, u4_bitstream_offset, pu4_bitstrm_buf, u4_ldz);
Yahui Hana082ab62023-07-14 14:41:39 +0800309
Yahui Hanad79ebb2023-07-19 17:02:21 +0800310 *pu4_bitstrm_ofst = u4_bitstream_offset;
Yahui Hana082ab62023-07-14 14:41:39 +0800311
Yahui Hanad79ebb2023-07-19 17:02:21 +0800312 return ((1 << u4_ldz) + u4_word - 1);
313}
Yahui Hana082ab62023-07-14 14:41:39 +0800314
Yahui Hanad79ebb2023-07-19 17:02:21 +0800315uint32_t reverseBytes(uint32_t num)
316{
317 uint32_t result = 0;
318
319 result |= (num & 0xff) << 24;
320 result |= (num & 0xff00) << 8;
321 result |= (num & 0xff0000) >> 8;
322 result |= (num & 0xff000000) >> 24;
323
324 return result;
Yahui Hana082ab62023-07-14 14:41:39 +0800325}
326
Gong Kefa504d72023-04-18 10:23:35 +0800327static void find_h264(uint8_t *data, size_t len, TS_Indexer_t *indexer, TSParser *stream)
328{
329 TS_Indexer_Event_t event;
330 uint8_t *nalu = data;
331 size_t pes_data_len = len;
332 size_t nalu_len;
Yahui Hana082ab62023-07-14 14:41:39 +0800333 uint8_t *p = NULL;
Gong Kefa504d72023-04-18 10:23:35 +0800334
335 memset(&event, 0, sizeof(event));
336 event.pid = stream->pid;
337 event.offset = stream->offset;
338
Yahui Hana082ab62023-07-14 14:41:39 +0800339 for (;;) {
Gong Kefa504d72023-04-18 10:23:35 +0800340 int left = pes_data_len - (nalu - data);
Yahui Han53b3c502023-08-04 10:36:58 +0800341 if (left <= 5) {
Gong Kefa504d72023-04-18 10:23:35 +0800342 memcpy(&stream->PES.data[0], nalu, left);
343 stream->PES.len = left;
344 break;
345 }
346
Yahui Hana082ab62023-07-14 14:41:39 +0800347 nalu = get_nalu(nalu, left, &nalu_len, 0);
Gong Kefa504d72023-04-18 10:23:35 +0800348 if (nalu == NULL)
349 break;
350
351 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x01) {
Yahui Hana082ab62023-07-14 14:41:39 +0800352 p = &nalu[3];
Yahui Hana082ab62023-07-14 14:41:39 +0800353 }
354
355 uint32_t offset = 0;
Yahui Han114ba4f2023-07-19 14:07:01 +0800356 uint32_t *pu4_bitstrm_buf = (uint32_t *)&p[1];
Yahui Hana082ab62023-07-14 14:41:39 +0800357 uint32_t *pu4_bitstrm_ofst = &offset;
358 if (p != NULL)
359 {
360 uint8_t nal_unit_type = (p[0] & 0x1f);
361 uint16_t u2_first_mb_in_slice;
362 uint8_t slice_type;
363
Yahui Hanad79ebb2023-07-19 17:02:21 +0800364 uint32_t reverseNum = reverseBytes(*pu4_bitstrm_buf);
365 u2_first_mb_in_slice = golomb_uev(pu4_bitstrm_ofst, &reverseNum);
366 slice_type = golomb_uev(pu4_bitstrm_ofst, &reverseNum);
Yahui Han63de7082023-07-12 18:30:10 +0800367
368 event.pts = stream->PES.pts;
Yahui Hana082ab62023-07-14 14:41:39 +0800369 if (nal_unit_type == NAL_TYPE_IDR) {
370 if (slice_type == 2 || slice_type == 7) {
371 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
372 } else if (slice_type == 4 || slice_type == 9) {
373 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
374 } else {
375 ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
376 nalu[0], nalu[1], nalu[2], nalu[3],
377 nalu[4], nalu[5], nalu[6], nalu[7]);
378 ERR("%s line%d invalid slice_type: %d, offset: %lx\n", __func__, __LINE__, slice_type, event.offset);
379 nalu += nalu_len;
380 continue;
381 }
382 } else if (nal_unit_type == NAL_TYPE_NON_IDR) {
383 //ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
384 // nalu[0], nalu[1], nalu[2], nalu[3],
385 // nalu[4], nalu[5], nalu[6], nalu[7]);
Yahui Han63de7082023-07-12 18:30:10 +0800386 if (slice_type == 0 || slice_type == 5) {
387 event.type = TS_INDEXER_EVENT_TYPE_AVC_P_SLICE;
388 } else if (slice_type == 1 || slice_type == 6) {
389 event.type = TS_INDEXER_EVENT_TYPE_AVC_B_SLICE;
390 } else if (slice_type == 2 || slice_type == 7) {
391 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
392 } else if (slice_type == 3 || slice_type == 8) {
393 event.type = TS_INDEXER_EVENT_TYPE_AVC_SP_SLICE;
394 } else if (slice_type == 4 || slice_type == 9) {
395 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
396 } else {
Yahui Hana082ab62023-07-14 14:41:39 +0800397 ERR("%s line%d invalid slice_type: %d\n", __func__, __LINE__, slice_type);
398 nalu += nalu_len;
399 continue;
Gong Kefa504d72023-04-18 10:23:35 +0800400 }
Yahui Han63de7082023-07-12 18:30:10 +0800401 } else {
402 nalu += nalu_len;
403 continue;
404 }
405
406 if (indexer->callback) {
407 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800408 }
409 }
410
411 nalu += nalu_len;
412 }
413
414 stream->PES.len = 0;
415}
416
417static void find_h265(uint8_t *data, int len, TS_Indexer_t *indexer, TSParser *stream)
418{
419 TS_Indexer_Event_t event;
420 uint8_t *nalu = data;
421 size_t pes_data_len = len;
422 size_t nalu_len;
423
424 memset(&event, 0, sizeof(event));
425 event.pid = stream->pid;
426 event.offset = stream->offset;
427
428 while (nalu != NULL) {
429 int left = pes_data_len - (nalu - data);
430 if (left <= 4) {
431 memcpy(&stream->PES.data[0], nalu, left);
432 stream->PES.len = left;
433 break;
434 }
435
Yahui Hana082ab62023-07-14 14:41:39 +0800436 nalu = get_nalu(nalu, left, &nalu_len, 1);
Gong Kefa504d72023-04-18 10:23:35 +0800437 if (nalu == NULL)
438 break;
439
Yahui Han53b3c502023-08-04 10:36:58 +0800440 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x01) {
441 int nalu_type = (nalu[3] & 0x7E) >> 1;
442 INF("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x, nalu_type: %d, offset: %#lx\n",
443 nalu[3], nalu[4], nalu[5], nalu[6], nalu[7], nalu[8], nalu_type, event.offset);
Yahui Han63de7082023-07-12 18:30:10 +0800444 switch (nalu_type) {
445 case HEVC_NALU_BLA_W_LP:
446 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_LP;
447 break;
448
449 case HEVC_NALU_BLA_W_RADL:
450 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_RADL;
451 break;
452
Yahui Hana082ab62023-07-14 14:41:39 +0800453 case HEVC_NALU_BLA_N_LP:
454 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_N_LP;
455 break;
456
Yahui Han63de7082023-07-12 18:30:10 +0800457 case HEVC_NALU_IDR_W_RADL:
458 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_W_RADL;
459 //INF("HEVC I-frame found\n");
460 break;
461
462 case HEVC_NALU_IDR_N_LP:
463 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_N_LP;
464 break;
465
466 case HEVC_NALU_TRAIL_CRA:
467 event.type = TS_INDEXER_EVENT_TYPE_HEVC_TRAIL_CRA;
468 break;
469
470 case HEVC_NALU_SPS:
471 event.type = TS_INDEXER_EVENT_TYPE_HEVC_SPS;
472 break;
473
474 case HEVC_NALU_AUD:
475 event.type = TS_INDEXER_EVENT_TYPE_HEVC_AUD;
476 break;
477
478 default:
479 nalu += nalu_len;
480 continue;
481 }
482
483 event.pts = stream->PES.pts;
484 if (indexer->callback) {
485 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800486 }
487 }
488
489 nalu += nalu_len;
490 }
Yahui Han63de7082023-07-12 18:30:10 +0800491
Gong Kefa504d72023-04-18 10:23:35 +0800492 stream->PES.len = 0;
493}
494
495/*Parse the PES packet*/
496static void
497pes_packet(TS_Indexer_t *ts_indexer, uint8_t *data, int len, TSParser *stream)
498{
499 uint8_t *p = data;
500 TS_Indexer_t *pi = ts_indexer;
501 int left = len;
502 TS_Indexer_Event_t event;
503
504 memset(&event, 0, sizeof(event));
505 event.pid = stream->pid;
506 event.offset = stream->offset;
507
508 INF("stream: %p, state: %d\n", stream, stream->PES.state);
509 if (stream->PES.state <= TS_INDEXER_STATE_INIT) {
510 INF("%s, invalid state\n", __func__);
511 stream->PES.len = 0;
512 return;
513 }
514
515 /* needs splice two pieces of data together if have cache data */
516 if (stream->PES.len > 0) {
517 INF("%s have cache data %d bytes\n", __func__, stream->PES.len);
518 memcpy(&stream->PES.data[stream->PES.len], data, len);
519 p = &stream->PES.data[0];
520 left = stream->PES.len + len;
521 stream->PES.len = left;
522 }
523
524 if (stream->PES.state == TS_INDEXER_STATE_TS_START) {
525 /* needs cache data if no enough data to parse PES header */
526 if (left < 6) {
527 if (stream->PES.len <= 0) {
528 memcpy(&stream->PES.data[0], p, left);
529 stream->PES.len = left;
530 }
531 INF("not enough ts payload len: %#x\n", left);
532 return;
533 }
534
535 // chect the PES packet start code prefix
536 if ((p[0] != 0) || (p[1] != 0) || (p[2] != 1)) {
537 stream->PES.len = 0;
538 stream->PES.state = TS_INDEXER_STATE_INIT;
539 INF("%s, not the expected start code!\n", __func__);
540 return;
541 }
542
543 p += 6;
544 left -= 6;
545 stream->PES.state = TS_INDEXER_STATE_PES_HEADER;
546 }
547
548 if (stream->PES.state == TS_INDEXER_STATE_PES_HEADER) {
549 if (left < 8) {
550 if (stream->PES.len <= 0) {
551 memcpy(&stream->PES.data[0], p, left);
552 stream->PES.len = left;
553 }
554 INF("not enough optional pes header len: %#x\n", left);
555 return;
556 }
557
558 int header_length = p[2];
559 if (p[1] & 0x80) {
560 // parser pts
561 p += 3;
562 left -= 3;
563 event.pts = stream->PES.pts = (((uint64_t)(p[0] & 0x0E) << 29) |
564 ((uint64_t)p[1] << 22) |
565 ((uint64_t)(p[2] & 0xFE) << 14) |
566 ((uint64_t)p[3] << 7) |
567 (((uint64_t)p[4] & 0xFE) >> 1));
568 INF("pts: %lx, pos:%lx\n", event.pts, event.offset);
569
570 if (stream == &pi->video_parser) {
571 event.type = TS_INDEXER_EVENT_TYPE_VIDEO_PTS;
572 } else {
573 event.type = TS_INDEXER_EVENT_TYPE_AUDIO_PTS;
574 }
575 if (pi->callback) {
576 pi->callback(pi, &event);
577 }
578 }
Yahui Han63de7082023-07-12 18:30:10 +0800579 if (stream->format != -1) {
580 stream->PES.state = TS_INDEXER_STATE_PES_PTS;
Gong Kefa504d72023-04-18 10:23:35 +0800581
Yahui Han63de7082023-07-12 18:30:10 +0800582 p += header_length;
583 left -= header_length;
584 } else {
585 stream->PES.state = TS_INDEXER_STATE_INIT;
586 left = 0;
587 }
Gong Kefa504d72023-04-18 10:23:35 +0800588 }
589
590 stream->PES.len = left;
591 if (left <= 0
592 || stream->PES.state < TS_INDEXER_STATE_PES_PTS) {
593 return;
594 }
595
596 INF("stream->format: %d, left: %d\n", stream->format, left);
597 switch (stream->format) {
598 case TS_INDEXER_VIDEO_FORMAT_MPEG2:
599 find_mpeg(p, left, pi, &pi->video_parser);
600 break;
601
602 case TS_INDEXER_VIDEO_FORMAT_H264:
603 find_h264(p, left, pi, &pi->video_parser);
604 break;
605
606 case TS_INDEXER_VIDEO_FORMAT_HEVC:
607 find_h265(p, left, pi, &pi->video_parser);
608 break;
609
610 default:
Yahui Han63de7082023-07-12 18:30:10 +0800611 stream->PES.state = TS_INDEXER_STATE_INIT;
612 stream->PES.len = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800613 break;
614 }
615}
616
617/*Parse the TS packet.*/
618static void
619ts_packet(TS_Indexer_t *ts_indexer, uint8_t *data)
620{
621 uint16_t pid;
622 uint8_t afc;
623 uint8_t *p = data;
624 TS_Indexer_t *pi = ts_indexer;
625 int len;
626 int is_start;
Yahui Han63de7082023-07-12 18:30:10 +0800627 TS_Indexer_Event_t event;
Gong Kefa504d72023-04-18 10:23:35 +0800628
629 is_start = p[1] & 0x40;
630 pid = ((p[1] & 0x1f) << 8) | p[2];
631 if (pid == 0x1fff)
632 return;
633
634 if ((pid != pi->video_parser.pid) &&
635 (pid != pi->audio_parser.pid)) {
636 return;
637 }
638
639 if (is_start) {
Yahui Han63de7082023-07-12 18:30:10 +0800640 memset(&event, 0, sizeof(event));
641 event.pid = pid;
642 event.offset = pi->offset;
643 event.type = TS_INDEXER_EVENT_TYPE_START_INDICATOR;
644 if (pi->callback) {
645 pi->callback(pi, &event);
646 }
647
Gong Kefa504d72023-04-18 10:23:35 +0800648 if (pid == pi->video_parser.pid) {
649 pi->video_parser.offset = pi->offset;
650 pi->video_parser.PES.state = TS_INDEXER_STATE_TS_START;
651 }
652 else if (pid == pi->audio_parser.pid) {
653 pi->audio_parser.offset = pi->offset;
654 pi->audio_parser.PES.state = TS_INDEXER_STATE_TS_START;
655 }
656 }
657
658 afc = (p[3] >> 4) & 0x03;
659
660 p += 4;
661 len = 184;
662
663 if (afc & 2) {
664 int adp_field_len = p[0];
Yahui Han63de7082023-07-12 18:30:10 +0800665 if (p[1] & 0x80) {
666 memset(&event, 0, sizeof(event));
667 event.pid = pid;
668 event.offset = pi->offset;
669 event.type = TS_INDEXER_EVENT_TYPE_DISCONTINUITY_INDICATOR;
670 if (pi->callback) {
671 pi->callback(pi, &event);
672 }
673 }
Gong Kefa504d72023-04-18 10:23:35 +0800674 p++;
675 len--;
676
677 p += adp_field_len;
678 len -= adp_field_len;
679
680 if (len < 0) {
681 ERR("illegal adaption field length!");
682 return;
683 }
684 }
685
686 // has payload
687 if ((afc & 1) && (len > 0)) {
688 // parser pes packet
689 pes_packet(pi, p, len, (pid == pi->video_parser.pid) ? &pi->video_parser : &pi->audio_parser);
690 }
691}
692
693/**
694 * Parse the TS stream and generate the index data.
695 * \param ts_indexer The TS indexer.
696 * \param data The TS data.
697 * \param len The length of the TS data in bytes.
698 * \return The left TS data length of bytes.
699 */
700int
701ts_indexer_parse (TS_Indexer_t *ts_indexer, uint8_t *data, int len)
702{
703 uint8_t *p = data;
704 int left = len;
705
706 if (ts_indexer == NULL || data == NULL || len <= 0)
707 return -1;
708
709 while (left > 0) {
710 // find the sync byte
711 if (*p == 0x47) {
712 if (left < TS_PKT_SIZE) {
713 INF("%s data length may not be 188-byte aligned\n", __func__);
714 return left;
715 }
716
717 // parse one ts packet
718 ts_packet(ts_indexer, p);
719 p += TS_PKT_SIZE;
720 left -= TS_PKT_SIZE;
721 ts_indexer->offset += TS_PKT_SIZE;
722 } else {
723 p++;
724 left--;
725 ts_indexer->offset++;
726 }
727 }
728
729 return left;
730}