blob: 87055c4c47e7169b7af8c9320fd900816a1c1d12 [file] [log] [blame]
Gong Kefa504d72023-04-18 10:23:35 +08001#include <stdio.h>
2#include <string.h>
3#include "ts_indexer.h"
4
5#define TS_PKT_SIZE (188)
6
7//#define TS_INDEXER_DEBUG
8#ifdef TS_INDEXER_DEBUG
9#define INF(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
10#else
11#define INF(fmt, ...)
12#endif
13
14#define ERR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
15
Yahui Hana082ab62023-07-14 14:41:39 +080016#define NAL_TYPE_NON_IDR 1 // 非 IDR NALU 类型
17#define NAL_TYPE_IDR 5 // IDR NALU 类型
Gong Kefa504d72023-04-18 10:23:35 +080018
Yahui Han63de7082023-07-12 18:30:10 +080019#define HEVC_NALU_BLA_W_LP 16
20#define HEVC_NALU_BLA_W_RADL 17
Yahui Hana082ab62023-07-14 14:41:39 +080021#define HEVC_NALU_BLA_N_LP 18
Yahui Han63de7082023-07-12 18:30:10 +080022#define HEVC_NALU_IDR_W_RADL 19
23#define HEVC_NALU_IDR_N_LP 20
24#define HEVC_NALU_TRAIL_CRA 21
25#define HEVC_NALU_SPS 33
26#define HEVC_NALU_AUD 35
27
Gong Kefa504d72023-04-18 10:23:35 +080028/**
29 * Initialize the TS indexer.
30 * \param ts_indexer The TS indexer to be initialized.
31 * \retval 0 On success.
32 * \retval -1 On error.
33 */
34int
35ts_indexer_init (TS_Indexer_t *ts_indexer)
36{
37 TSParser init_parser;
38
39 if (ts_indexer == NULL) {
40 return -1;
41 }
42
43 memset(&init_parser, 0, sizeof(TSParser));
44 init_parser.pid = 0x1fff;
45 init_parser.format = -1;
46 init_parser.PES.pts = -1;
47 init_parser.PES.offset = 0;
48 init_parser.PES.len = 0;
49 init_parser.PES.state = TS_INDEXER_STATE_INIT;
50
51 memcpy(&ts_indexer->video_parser, &init_parser, sizeof(TSParser));
52 memcpy(&ts_indexer->audio_parser, &init_parser, sizeof(TSParser));
53 ts_indexer->callback = NULL;
54 ts_indexer->offset = 0;
55
56 return 0;
57}
58
59/**
60 * Release the TS indexer.
61 * \param ts_indexer The TS indexer to be released.
62 */
63void
64ts_indexer_destroy (TS_Indexer_t *ts_indexer)
65{
66 return;
67}
68
69/**
70 * Set the video format.
71 * \param ts_indexer The TS indexer.
72 * \param format The stream format.
73 * \retval 0 On success.
74 * \retval -1 On error.
75 */
76int
77ts_indexer_set_video_format (TS_Indexer_t *ts_indexer, TS_Indexer_StreamFormat_t format)
78{
79 if (ts_indexer == NULL)
80 return -1;
81
82 ts_indexer->video_parser.format = format;
83
84 return 0;
85}
86
87/**
88 * Set the video PID.
89 * \param ts_indexer The TS indexer.
90 * \param pid The video PID.
91 * \retval 0 On success.
92 * \retval -1 On error.
93 */
94int
95ts_indexer_set_video_pid (TS_Indexer_t *ts_indexer, int pid)
96{
97 if (ts_indexer == NULL)
98 return -1;
99
100
101 TSParser *parser = &ts_indexer->video_parser;
102 parser->pid = pid;
103 parser->offset = 0;
104 parser->PES.pts = -1;
105 parser->PES.offset = 0;
106 parser->PES.len = 0;
107 parser->PES.state = TS_INDEXER_STATE_INIT;
108
109 return 0;
110}
111
112/**
113 * Set the audio PID.
114 * \param ts_indexer The TS indexer.
115 * \param pid The audio PID.
116 * \retval 0 On success.
117 * \retval -1 On error.
118 */
119int
120ts_indexer_set_audio_pid (TS_Indexer_t *ts_indexer, int pid)
121{
122 if (ts_indexer == NULL)
123 return -1;
124
125 TSParser *parser = &ts_indexer->audio_parser;
126 parser->pid = pid;
127 parser->offset = 0;
128 parser->PES.pts = -1;
129 parser->PES.offset = 0;
130 parser->PES.len = 0;
131 parser->PES.state = TS_INDEXER_STATE_INIT;
132
133 return 0;
134}
135
136/**
137 * Set the event callback function.
138 * \param ts_indexer The TS indexer.
139 * \param callback The event callback function.
140 * \retval 0 On success.
141 * \retval -1 On error.
142 */
143int
144ts_indexer_set_event_callback (TS_Indexer_t *ts_indexer, TS_Indexer_EventCallback_t callback)
145{
146 ts_indexer->callback = callback;
147
148 return 0;
149}
150
151static void find_mpeg(uint8_t *data, int len, TS_Indexer_t *indexer, TSParser *stream)
152{
153 int i;
154 uint32_t needle = 0;
Yahui Han63de7082023-07-12 18:30:10 +0800155 uint32_t needle1 = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800156 uint8_t *haystack = data;
157 int haystack_len = len;
158 int left = len;
159 // start code of picture header
160 uint8_t arr[4] = {0x00, 0x00, 0x01, 0x00};
Yahui Han63de7082023-07-12 18:30:10 +0800161 // start code of sequence header
162 uint8_t arr1[4] = {0x00, 0x00, 0x01, 0xb3};
Gong Kefa504d72023-04-18 10:23:35 +0800163 TS_Indexer_Event_t event;
164
165 /* mpeg header needs at least 4 bytes */
166 if (left < 4) {
167 memcpy(&stream->PES.data[0], &haystack, left);
168 stream->PES.len = left;
169 return;
170 }
171
172 memset(&event, 0, sizeof(event));
173 event.pid = stream->pid;
174 event.offset = stream->offset;
175
176 for (i = 0; i < 4; ++i) {
177 needle += (arr[i] << (8 * i));
178 }
179
Yahui Han63de7082023-07-12 18:30:10 +0800180 for (i = 0; i < 4; ++i) {
181 needle1 += (arr1[i] << (8 * i));
182 }
183
Gong Kefa504d72023-04-18 10:23:35 +0800184 for (i = 0; i < haystack_len - sizeof(needle) + 1;) {
Yahui Han63de7082023-07-12 18:30:10 +0800185 if (left < 5) {
186 INF("MPEG2 picture header across TS Packet\n");
187
188 /* MEPG2 picture header across TS packet, should cache the left data */
189 memcpy(&stream->PES.data[0], haystack + i, left);
190 stream->PES.len = left;
191 return;
192 }
193
Gong Kefa504d72023-04-18 10:23:35 +0800194 if (*(uint32_t *)(haystack + i) == needle) {
195 // picture header found
Yahui Han63de7082023-07-12 18:30:10 +0800196 int frame_type = (haystack[i + 5] >> 3) & 0x7;
197 switch (frame_type) {
198 case 1:
199 INF("I frame found, offset: %lx\n", event.offset);
200 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_I_FRAME;
201 break;
Gong Kefa504d72023-04-18 10:23:35 +0800202
Yahui Han63de7082023-07-12 18:30:10 +0800203 case 2:
204 INF("P frame found, offset: %lx\n", event.offset);
205 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_P_FRAME;
206 break;
207
208 case 3:
209 INF("B frame found, offset: %lx\n", event.offset);
210 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_B_FRAME;
211 break;
212
213 default:
214 i += 5;
215 left -= 5;
216 continue;
217
Gong Kefa504d72023-04-18 10:23:35 +0800218 }
219
Yahui Han63de7082023-07-12 18:30:10 +0800220 event.pts = stream->PES.pts;
221 if (indexer->callback) {
222 indexer->callback(indexer, &event);
223 }
224
225 i += 5;
226 left -= 5;
227 } else if (*(uint32_t *)(haystack + i) == needle1) {
228 // sequence header found
229 event.type = TS_INDEXER_EVENT_TYPE_MPEG2_SEQUENCE;
230 event.pts = stream->PES.pts;
231 if (indexer->callback) {
232 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800233 }
234
235 i += 5;
236 left -= 5;
237 } else {
238 i ++;
239 left --;
240 }
241 }
242
243 if (left > 0) {
244 memcpy(&stream->PES.data[0], &haystack[i], left);
245 stream->PES.len = left;
246 } else {
247 stream->PES.len = 0;
248 }
249}
250
Yahui Hana082ab62023-07-14 14:41:39 +0800251static 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 +0800252{
Yahui Hana082ab62023-07-14 14:41:39 +0800253 size_t i = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800254 uint8_t *p = data;
255
256 if (len == 0)
257 return NULL;
258
259 //INF("%s enter, len:%#lx\n", __func__, len);
Yahui Hana082ab62023-07-14 14:41:39 +0800260if (is_hevc) {
261 while (i < len - 5) {
262 if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x00 && p[i+3] == 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 Hana082ab62023-07-14 14:41:39 +0800268 for (size_t j = i ; j < len - 5; ++j) {
269 if (p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x00 && p[j+3] == 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 Hana082ab62023-07-14 14:41:39 +0800291 while ( i < len - 4) {
292 if ((p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01) ||
293 (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x00 && p[i+3] == 0x01)) {
294 uint8_t *frame_data = data + i;
295 size_t frame_data_len = 0;
296
297 if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01) {
298 i += 3;
299 //ERR("find 0x00 0x00 0x01 startcode\n");
300 } else {
301 i += 4;
302 //ERR("find 0x00 0x00 0x00 0x01 startcode\n");
303 }
304
305 //INF("%s start code prefix\n", __func__);
306 size_t j = i;
307 while (j < len - 4) {
308 if ((p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x01) ||
309 (p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x00 && p[j+3] == 0x01)) {
310 frame_data_len = j - i;
311 break;
312 }
313 j ++;
314 }
315
316 if (frame_data_len > 0) {
317 *nalu_len = frame_data_len;
318 return frame_data;
319 } else {
320 frame_data_len = len - i;
321 *nalu_len = frame_data_len;
322 return frame_data;
323 }
324 } else {
325 i ++;
326 }
327 }
328
329 return NULL;
330}
331
332uint32_t golomb_uev(uint32_t *pu4_bitstrm_ofst, uint8_t *pu1_bitstrm_buf)
333{
334 int u4_bitstream_offset = *pu4_bitstrm_ofst;
335 uint32_t leadingZeroBits = -1;
336 uint32_t codeNum = 0;
337
338 if (u4_bitstream_offset >= 8 || u4_bitstream_offset < 0) {
339 //ERR("error!!!! ofset: %d\n", *pu4_bitstrm_ofst);
340 //ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
341 //pu1_bitstrm_buf[0], pu1_bitstrm_buf[1], pu1_bitstrm_buf[2],
342 //pu1_bitstrm_buf[3], pu1_bitstrm_buf[4], pu1_bitstrm_buf[5]);
343 return -1;
344 }
345
346 /* count the leading zero bits */
347 for (uint8_t b = 0; !b && u4_bitstream_offset < 8; leadingZeroBits++ )
348 {
349 b = ((*pu1_bitstrm_buf) >> (7 - u4_bitstream_offset)) & 0x01;
350 if (!b) {
351 u4_bitstream_offset++;
352 }
353 }
354
355 for (int i = 0; i < leadingZeroBits; i++) {
356 codeNum |= (((*pu1_bitstrm_buf) >> (7 - u4_bitstream_offset - 1 - i)) & 0x01);
357 if (i < leadingZeroBits - 1)
358 codeNum <<= 1;
359 }
360
361 codeNum += ((1 << leadingZeroBits) - 1);
362 *pu4_bitstrm_ofst = (u4_bitstream_offset + leadingZeroBits + 1);
363
364 return codeNum;
365}
366
Gong Kefa504d72023-04-18 10:23:35 +0800367static void find_h264(uint8_t *data, size_t len, TS_Indexer_t *indexer, TSParser *stream)
368{
369 TS_Indexer_Event_t event;
370 uint8_t *nalu = data;
371 size_t pes_data_len = len;
372 size_t nalu_len;
Yahui Hana082ab62023-07-14 14:41:39 +0800373 uint8_t *p = NULL;
Gong Kefa504d72023-04-18 10:23:35 +0800374
375 memset(&event, 0, sizeof(event));
376 event.pid = stream->pid;
377 event.offset = stream->offset;
378
Yahui Hana082ab62023-07-14 14:41:39 +0800379 for (;;) {
Gong Kefa504d72023-04-18 10:23:35 +0800380 int left = pes_data_len - (nalu - data);
Yahui Hana082ab62023-07-14 14:41:39 +0800381 if (left <= 6) {
Gong Kefa504d72023-04-18 10:23:35 +0800382 memcpy(&stream->PES.data[0], nalu, left);
383 stream->PES.len = left;
384 break;
385 }
386
Yahui Hana082ab62023-07-14 14:41:39 +0800387 nalu = get_nalu(nalu, left, &nalu_len, 0);
Gong Kefa504d72023-04-18 10:23:35 +0800388 if (nalu == NULL)
389 break;
390
391 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x01) {
Yahui Hana082ab62023-07-14 14:41:39 +0800392 p = &nalu[3];
393 } else if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x00 && nalu[3] == 0x01) {
394 p = &nalu[4];
395 }
396
397 uint32_t offset = 0;
398 uint8_t *pu1_bitstrm_buf = &p[1];
399 uint32_t *pu4_bitstrm_ofst = &offset;
400 if (p != NULL)
401 {
402 uint8_t nal_unit_type = (p[0] & 0x1f);
403 uint16_t u2_first_mb_in_slice;
404 uint8_t slice_type;
405
406 u2_first_mb_in_slice = golomb_uev(pu4_bitstrm_ofst, pu1_bitstrm_buf);
407 slice_type = golomb_uev(pu4_bitstrm_ofst, pu1_bitstrm_buf);
Yahui Han63de7082023-07-12 18:30:10 +0800408
409 event.pts = stream->PES.pts;
Yahui Hana082ab62023-07-14 14:41:39 +0800410 if (nal_unit_type == NAL_TYPE_IDR) {
411 if (slice_type == 2 || slice_type == 7) {
412 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
413 } else if (slice_type == 4 || slice_type == 9) {
414 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
415 } else {
416 ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
417 nalu[0], nalu[1], nalu[2], nalu[3],
418 nalu[4], nalu[5], nalu[6], nalu[7]);
419 ERR("%s line%d invalid slice_type: %d, offset: %lx\n", __func__, __LINE__, slice_type, event.offset);
420 nalu += nalu_len;
421 continue;
422 }
423 } else if (nal_unit_type == NAL_TYPE_NON_IDR) {
424 //ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
425 // nalu[0], nalu[1], nalu[2], nalu[3],
426 // nalu[4], nalu[5], nalu[6], nalu[7]);
Yahui Han63de7082023-07-12 18:30:10 +0800427 if (slice_type == 0 || slice_type == 5) {
428 event.type = TS_INDEXER_EVENT_TYPE_AVC_P_SLICE;
429 } else if (slice_type == 1 || slice_type == 6) {
430 event.type = TS_INDEXER_EVENT_TYPE_AVC_B_SLICE;
431 } else if (slice_type == 2 || slice_type == 7) {
432 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
433 } else if (slice_type == 3 || slice_type == 8) {
434 event.type = TS_INDEXER_EVENT_TYPE_AVC_SP_SLICE;
435 } else if (slice_type == 4 || slice_type == 9) {
436 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
437 } else {
Yahui Hana082ab62023-07-14 14:41:39 +0800438 ERR("%s line%d invalid slice_type: %d\n", __func__, __LINE__, slice_type);
439 nalu += nalu_len;
440 continue;
Gong Kefa504d72023-04-18 10:23:35 +0800441 }
Yahui Han63de7082023-07-12 18:30:10 +0800442 } else {
443 nalu += nalu_len;
444 continue;
445 }
446
447 if (indexer->callback) {
448 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800449 }
450 }
451
452 nalu += nalu_len;
453 }
454
455 stream->PES.len = 0;
456}
457
458static void find_h265(uint8_t *data, int len, TS_Indexer_t *indexer, TSParser *stream)
459{
460 TS_Indexer_Event_t event;
461 uint8_t *nalu = data;
462 size_t pes_data_len = len;
463 size_t nalu_len;
464
465 memset(&event, 0, sizeof(event));
466 event.pid = stream->pid;
467 event.offset = stream->offset;
468
469 while (nalu != NULL) {
470 int left = pes_data_len - (nalu - data);
471 if (left <= 4) {
472 memcpy(&stream->PES.data[0], nalu, left);
473 stream->PES.len = left;
474 break;
475 }
476
Yahui Hana082ab62023-07-14 14:41:39 +0800477 nalu = get_nalu(nalu, left, &nalu_len, 1);
Gong Kefa504d72023-04-18 10:23:35 +0800478 if (nalu == NULL)
479 break;
480
Yahui Hana082ab62023-07-14 14:41:39 +0800481 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x00 && nalu[3] == 0x01) {
482 int nalu_type = (nalu[4] & 0x7E) >> 1;
Gong Kefa504d72023-04-18 10:23:35 +0800483 //INF("nalu[3]: %#x, nalu_type: %#x\n", nalu[3], nalu_type);
Yahui Han63de7082023-07-12 18:30:10 +0800484 switch (nalu_type) {
485 case HEVC_NALU_BLA_W_LP:
486 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_LP;
487 break;
488
489 case HEVC_NALU_BLA_W_RADL:
490 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_RADL;
491 break;
492
Yahui Hana082ab62023-07-14 14:41:39 +0800493 case HEVC_NALU_BLA_N_LP:
494 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_N_LP;
495 break;
496
Yahui Han63de7082023-07-12 18:30:10 +0800497 case HEVC_NALU_IDR_W_RADL:
498 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_W_RADL;
499 //INF("HEVC I-frame found\n");
500 break;
501
502 case HEVC_NALU_IDR_N_LP:
503 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_N_LP;
504 break;
505
506 case HEVC_NALU_TRAIL_CRA:
507 event.type = TS_INDEXER_EVENT_TYPE_HEVC_TRAIL_CRA;
508 break;
509
510 case HEVC_NALU_SPS:
511 event.type = TS_INDEXER_EVENT_TYPE_HEVC_SPS;
512 break;
513
514 case HEVC_NALU_AUD:
515 event.type = TS_INDEXER_EVENT_TYPE_HEVC_AUD;
516 break;
517
518 default:
519 nalu += nalu_len;
520 continue;
521 }
522
523 event.pts = stream->PES.pts;
524 if (indexer->callback) {
525 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800526 }
527 }
528
529 nalu += nalu_len;
530 }
Yahui Han63de7082023-07-12 18:30:10 +0800531
Gong Kefa504d72023-04-18 10:23:35 +0800532 stream->PES.len = 0;
533}
534
535/*Parse the PES packet*/
536static void
537pes_packet(TS_Indexer_t *ts_indexer, uint8_t *data, int len, TSParser *stream)
538{
539 uint8_t *p = data;
540 TS_Indexer_t *pi = ts_indexer;
541 int left = len;
542 TS_Indexer_Event_t event;
543
544 memset(&event, 0, sizeof(event));
545 event.pid = stream->pid;
546 event.offset = stream->offset;
547
548 INF("stream: %p, state: %d\n", stream, stream->PES.state);
549 if (stream->PES.state <= TS_INDEXER_STATE_INIT) {
550 INF("%s, invalid state\n", __func__);
551 stream->PES.len = 0;
552 return;
553 }
554
555 /* needs splice two pieces of data together if have cache data */
556 if (stream->PES.len > 0) {
557 INF("%s have cache data %d bytes\n", __func__, stream->PES.len);
558 memcpy(&stream->PES.data[stream->PES.len], data, len);
559 p = &stream->PES.data[0];
560 left = stream->PES.len + len;
561 stream->PES.len = left;
562 }
563
564 if (stream->PES.state == TS_INDEXER_STATE_TS_START) {
565 /* needs cache data if no enough data to parse PES header */
566 if (left < 6) {
567 if (stream->PES.len <= 0) {
568 memcpy(&stream->PES.data[0], p, left);
569 stream->PES.len = left;
570 }
571 INF("not enough ts payload len: %#x\n", left);
572 return;
573 }
574
575 // chect the PES packet start code prefix
576 if ((p[0] != 0) || (p[1] != 0) || (p[2] != 1)) {
577 stream->PES.len = 0;
578 stream->PES.state = TS_INDEXER_STATE_INIT;
579 INF("%s, not the expected start code!\n", __func__);
580 return;
581 }
582
583 p += 6;
584 left -= 6;
585 stream->PES.state = TS_INDEXER_STATE_PES_HEADER;
586 }
587
588 if (stream->PES.state == TS_INDEXER_STATE_PES_HEADER) {
589 if (left < 8) {
590 if (stream->PES.len <= 0) {
591 memcpy(&stream->PES.data[0], p, left);
592 stream->PES.len = left;
593 }
594 INF("not enough optional pes header len: %#x\n", left);
595 return;
596 }
597
598 int header_length = p[2];
599 if (p[1] & 0x80) {
600 // parser pts
601 p += 3;
602 left -= 3;
603 event.pts = stream->PES.pts = (((uint64_t)(p[0] & 0x0E) << 29) |
604 ((uint64_t)p[1] << 22) |
605 ((uint64_t)(p[2] & 0xFE) << 14) |
606 ((uint64_t)p[3] << 7) |
607 (((uint64_t)p[4] & 0xFE) >> 1));
608 INF("pts: %lx, pos:%lx\n", event.pts, event.offset);
609
610 if (stream == &pi->video_parser) {
611 event.type = TS_INDEXER_EVENT_TYPE_VIDEO_PTS;
612 } else {
613 event.type = TS_INDEXER_EVENT_TYPE_AUDIO_PTS;
614 }
615 if (pi->callback) {
616 pi->callback(pi, &event);
617 }
618 }
Yahui Han63de7082023-07-12 18:30:10 +0800619 if (stream->format != -1) {
620 stream->PES.state = TS_INDEXER_STATE_PES_PTS;
Gong Kefa504d72023-04-18 10:23:35 +0800621
Yahui Han63de7082023-07-12 18:30:10 +0800622 p += header_length;
623 left -= header_length;
624 } else {
625 stream->PES.state = TS_INDEXER_STATE_INIT;
626 left = 0;
627 }
Gong Kefa504d72023-04-18 10:23:35 +0800628 }
629
630 stream->PES.len = left;
631 if (left <= 0
632 || stream->PES.state < TS_INDEXER_STATE_PES_PTS) {
633 return;
634 }
635
636 INF("stream->format: %d, left: %d\n", stream->format, left);
637 switch (stream->format) {
638 case TS_INDEXER_VIDEO_FORMAT_MPEG2:
639 find_mpeg(p, left, pi, &pi->video_parser);
640 break;
641
642 case TS_INDEXER_VIDEO_FORMAT_H264:
643 find_h264(p, left, pi, &pi->video_parser);
644 break;
645
646 case TS_INDEXER_VIDEO_FORMAT_HEVC:
647 find_h265(p, left, pi, &pi->video_parser);
648 break;
649
650 default:
Yahui Han63de7082023-07-12 18:30:10 +0800651 stream->PES.state = TS_INDEXER_STATE_INIT;
652 stream->PES.len = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800653 break;
654 }
655}
656
657/*Parse the TS packet.*/
658static void
659ts_packet(TS_Indexer_t *ts_indexer, uint8_t *data)
660{
661 uint16_t pid;
662 uint8_t afc;
663 uint8_t *p = data;
664 TS_Indexer_t *pi = ts_indexer;
665 int len;
666 int is_start;
Yahui Han63de7082023-07-12 18:30:10 +0800667 TS_Indexer_Event_t event;
Gong Kefa504d72023-04-18 10:23:35 +0800668
669 is_start = p[1] & 0x40;
670 pid = ((p[1] & 0x1f) << 8) | p[2];
671 if (pid == 0x1fff)
672 return;
673
674 if ((pid != pi->video_parser.pid) &&
675 (pid != pi->audio_parser.pid)) {
676 return;
677 }
678
679 if (is_start) {
Yahui Han63de7082023-07-12 18:30:10 +0800680 memset(&event, 0, sizeof(event));
681 event.pid = pid;
682 event.offset = pi->offset;
683 event.type = TS_INDEXER_EVENT_TYPE_START_INDICATOR;
684 if (pi->callback) {
685 pi->callback(pi, &event);
686 }
687
Gong Kefa504d72023-04-18 10:23:35 +0800688 if (pid == pi->video_parser.pid) {
689 pi->video_parser.offset = pi->offset;
690 pi->video_parser.PES.state = TS_INDEXER_STATE_TS_START;
691 }
692 else if (pid == pi->audio_parser.pid) {
693 pi->audio_parser.offset = pi->offset;
694 pi->audio_parser.PES.state = TS_INDEXER_STATE_TS_START;
695 }
696 }
697
698 afc = (p[3] >> 4) & 0x03;
699
700 p += 4;
701 len = 184;
702
703 if (afc & 2) {
704 int adp_field_len = p[0];
Yahui Han63de7082023-07-12 18:30:10 +0800705 if (p[1] & 0x80) {
706 memset(&event, 0, sizeof(event));
707 event.pid = pid;
708 event.offset = pi->offset;
709 event.type = TS_INDEXER_EVENT_TYPE_DISCONTINUITY_INDICATOR;
710 if (pi->callback) {
711 pi->callback(pi, &event);
712 }
713 }
Gong Kefa504d72023-04-18 10:23:35 +0800714 p++;
715 len--;
716
717 p += adp_field_len;
718 len -= adp_field_len;
719
720 if (len < 0) {
721 ERR("illegal adaption field length!");
722 return;
723 }
724 }
725
726 // has payload
727 if ((afc & 1) && (len > 0)) {
728 // parser pes packet
729 pes_packet(pi, p, len, (pid == pi->video_parser.pid) ? &pi->video_parser : &pi->audio_parser);
730 }
731}
732
733/**
734 * Parse the TS stream and generate the index data.
735 * \param ts_indexer The TS indexer.
736 * \param data The TS data.
737 * \param len The length of the TS data in bytes.
738 * \return The left TS data length of bytes.
739 */
740int
741ts_indexer_parse (TS_Indexer_t *ts_indexer, uint8_t *data, int len)
742{
743 uint8_t *p = data;
744 int left = len;
745
746 if (ts_indexer == NULL || data == NULL || len <= 0)
747 return -1;
748
749 while (left > 0) {
750 // find the sync byte
751 if (*p == 0x47) {
752 if (left < TS_PKT_SIZE) {
753 INF("%s data length may not be 188-byte aligned\n", __func__);
754 return left;
755 }
756
757 // parse one ts packet
758 ts_packet(ts_indexer, p);
759 p += TS_PKT_SIZE;
760 left -= TS_PKT_SIZE;
761 ts_indexer->offset += TS_PKT_SIZE;
762 } else {
763 p++;
764 left--;
765 ts_indexer->offset++;
766 }
767 }
768
769 return left;
770}