blob: cd1a67f2248b084c86deb37efe0c169740474ec5 [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 Hana082ab62023-07-14 14:41:39 +0800261if (is_hevc) {
262 while (i < len - 5) {
263 if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x00 && p[i+3] == 0x01) {
Gong Kefa504d72023-04-18 10:23:35 +0800264 uint8_t *frame_data = data + i;
265 size_t frame_data_len = 0;
266
Yahui Hana082ab62023-07-14 14:41:39 +0800267 i += 4;
Gong Kefa504d72023-04-18 10:23:35 +0800268 //INF("%s start code prefix\n", __func__);
Yahui Hana082ab62023-07-14 14:41:39 +0800269 for (size_t j = i ; j < len - 5; ++j) {
270 if (p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x00 && p[j+3] == 0x01) {
Gong Kefa504d72023-04-18 10:23:35 +0800271 frame_data_len = j - i;
272 break;
273 }
274 }
275
276 if (frame_data_len > 0) {
277 *nalu_len = frame_data_len;
278 return frame_data;
279 } else {
280 frame_data_len = len - i;
281 *nalu_len = frame_data_len;
282 return frame_data;
283 }
Yahui Hana082ab62023-07-14 14:41:39 +0800284 } else {
285 i ++;
Gong Kefa504d72023-04-18 10:23:35 +0800286 }
287 }
288
289 return NULL;
290}
291
Yahui Hana082ab62023-07-14 14:41:39 +0800292 while ( i < len - 4) {
293 if ((p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01) ||
294 (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x00 && p[i+3] == 0x01)) {
295 uint8_t *frame_data = data + i;
296 size_t frame_data_len = 0;
297
298 if (p[i] == 0x00 && p[i+1] == 0x00 && p[i+2] == 0x01) {
299 i += 3;
300 //ERR("find 0x00 0x00 0x01 startcode\n");
301 } else {
302 i += 4;
303 //ERR("find 0x00 0x00 0x00 0x01 startcode\n");
304 }
305
306 //INF("%s start code prefix\n", __func__);
307 size_t j = i;
308 while (j < len - 4) {
309 if ((p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x01) ||
310 (p[j] == 0x00 && p[j+1] == 0x00 && p[j+2] == 0x00 && p[j+3] == 0x01)) {
311 frame_data_len = j - i;
312 break;
313 }
314 j ++;
315 }
316
317 if (frame_data_len > 0) {
318 *nalu_len = frame_data_len;
319 return frame_data;
320 } else {
321 frame_data_len = len - i;
322 *nalu_len = frame_data_len;
323 return frame_data;
324 }
325 } else {
326 i ++;
327 }
328 }
329
330 return NULL;
331}
332
Yahui Han114ba4f2023-07-19 14:07:01 +0800333uint32_t golomb_uev(uint32_t *pu4_bitstrm_ofst, uint32_t *pu4_bitstrm_buf)
Yahui Hana082ab62023-07-14 14:41:39 +0800334{
Yahui Hanad79ebb2023-07-19 17:02:21 +0800335 uint32_t u4_bitstream_offset = *pu4_bitstrm_ofst;
336 uint32_t u4_word, u4_ldz;
Yahui Hana082ab62023-07-14 14:41:39 +0800337
Yahui Hanad79ebb2023-07-19 17:02:21 +0800338 /* Find leading zeros in next 32 bits */
339 NEXTBITS_32(u4_word, u4_bitstream_offset, pu4_bitstrm_buf);
340 u4_ldz = CLZ(u4_word);
341 //printf("u4_ldz: %d, u4_word: %#x, offset: %d, pu4_bitstrm_buf: %#x\n",
342 // u4_ldz, u4_word, u4_bitstream_offset, *pu4_bitstrm_buf);
Yahui Hana082ab62023-07-14 14:41:39 +0800343
Yahui Hanad79ebb2023-07-19 17:02:21 +0800344 /* Flush the ps_bitstrm */
345 u4_bitstream_offset += (u4_ldz + 1);
Yahui Han114ba4f2023-07-19 14:07:01 +0800346
Yahui Hanad79ebb2023-07-19 17:02:21 +0800347 /* Read the suffix from the ps_bitstrm */
348 u4_word = 0;
349 if (u4_ldz)
350 GETBITS(u4_word, u4_bitstream_offset, pu4_bitstrm_buf, u4_ldz);
Yahui Hana082ab62023-07-14 14:41:39 +0800351
Yahui Hanad79ebb2023-07-19 17:02:21 +0800352 *pu4_bitstrm_ofst = u4_bitstream_offset;
Yahui Hana082ab62023-07-14 14:41:39 +0800353
Yahui Hanad79ebb2023-07-19 17:02:21 +0800354 return ((1 << u4_ldz) + u4_word - 1);
355}
Yahui Hana082ab62023-07-14 14:41:39 +0800356
Yahui Hanad79ebb2023-07-19 17:02:21 +0800357uint32_t reverseBytes(uint32_t num)
358{
359 uint32_t result = 0;
360
361 result |= (num & 0xff) << 24;
362 result |= (num & 0xff00) << 8;
363 result |= (num & 0xff0000) >> 8;
364 result |= (num & 0xff000000) >> 24;
365
366 return result;
Yahui Hana082ab62023-07-14 14:41:39 +0800367}
368
Gong Kefa504d72023-04-18 10:23:35 +0800369static void find_h264(uint8_t *data, size_t len, TS_Indexer_t *indexer, TSParser *stream)
370{
371 TS_Indexer_Event_t event;
372 uint8_t *nalu = data;
373 size_t pes_data_len = len;
374 size_t nalu_len;
Yahui Hana082ab62023-07-14 14:41:39 +0800375 uint8_t *p = NULL;
Gong Kefa504d72023-04-18 10:23:35 +0800376
377 memset(&event, 0, sizeof(event));
378 event.pid = stream->pid;
379 event.offset = stream->offset;
380
Yahui Hana082ab62023-07-14 14:41:39 +0800381 for (;;) {
Gong Kefa504d72023-04-18 10:23:35 +0800382 int left = pes_data_len - (nalu - data);
Yahui Hana082ab62023-07-14 14:41:39 +0800383 if (left <= 6) {
Gong Kefa504d72023-04-18 10:23:35 +0800384 memcpy(&stream->PES.data[0], nalu, left);
385 stream->PES.len = left;
386 break;
387 }
388
Yahui Hana082ab62023-07-14 14:41:39 +0800389 nalu = get_nalu(nalu, left, &nalu_len, 0);
Gong Kefa504d72023-04-18 10:23:35 +0800390 if (nalu == NULL)
391 break;
392
393 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x01) {
Yahui Hana082ab62023-07-14 14:41:39 +0800394 p = &nalu[3];
395 } else if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x00 && nalu[3] == 0x01) {
396 p = &nalu[4];
397 }
398
399 uint32_t offset = 0;
Yahui Han114ba4f2023-07-19 14:07:01 +0800400 uint32_t *pu4_bitstrm_buf = (uint32_t *)&p[1];
Yahui Hana082ab62023-07-14 14:41:39 +0800401 uint32_t *pu4_bitstrm_ofst = &offset;
402 if (p != NULL)
403 {
404 uint8_t nal_unit_type = (p[0] & 0x1f);
405 uint16_t u2_first_mb_in_slice;
406 uint8_t slice_type;
407
Yahui Hanad79ebb2023-07-19 17:02:21 +0800408 uint32_t reverseNum = reverseBytes(*pu4_bitstrm_buf);
409 u2_first_mb_in_slice = golomb_uev(pu4_bitstrm_ofst, &reverseNum);
410 slice_type = golomb_uev(pu4_bitstrm_ofst, &reverseNum);
Yahui Han63de7082023-07-12 18:30:10 +0800411
412 event.pts = stream->PES.pts;
Yahui Hana082ab62023-07-14 14:41:39 +0800413 if (nal_unit_type == NAL_TYPE_IDR) {
414 if (slice_type == 2 || slice_type == 7) {
415 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
416 } else if (slice_type == 4 || slice_type == 9) {
417 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
418 } else {
419 ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
420 nalu[0], nalu[1], nalu[2], nalu[3],
421 nalu[4], nalu[5], nalu[6], nalu[7]);
422 ERR("%s line%d invalid slice_type: %d, offset: %lx\n", __func__, __LINE__, slice_type, event.offset);
423 nalu += nalu_len;
424 continue;
425 }
426 } else if (nal_unit_type == NAL_TYPE_NON_IDR) {
427 //ERR("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
428 // nalu[0], nalu[1], nalu[2], nalu[3],
429 // nalu[4], nalu[5], nalu[6], nalu[7]);
Yahui Han63de7082023-07-12 18:30:10 +0800430 if (slice_type == 0 || slice_type == 5) {
431 event.type = TS_INDEXER_EVENT_TYPE_AVC_P_SLICE;
432 } else if (slice_type == 1 || slice_type == 6) {
433 event.type = TS_INDEXER_EVENT_TYPE_AVC_B_SLICE;
434 } else if (slice_type == 2 || slice_type == 7) {
435 event.type = TS_INDEXER_EVENT_TYPE_AVC_I_SLICE;
436 } else if (slice_type == 3 || slice_type == 8) {
437 event.type = TS_INDEXER_EVENT_TYPE_AVC_SP_SLICE;
438 } else if (slice_type == 4 || slice_type == 9) {
439 event.type = TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE;
440 } else {
Yahui Hana082ab62023-07-14 14:41:39 +0800441 ERR("%s line%d invalid slice_type: %d\n", __func__, __LINE__, slice_type);
442 nalu += nalu_len;
443 continue;
Gong Kefa504d72023-04-18 10:23:35 +0800444 }
Yahui Han63de7082023-07-12 18:30:10 +0800445 } else {
446 nalu += nalu_len;
447 continue;
448 }
449
450 if (indexer->callback) {
451 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800452 }
453 }
454
455 nalu += nalu_len;
456 }
457
458 stream->PES.len = 0;
459}
460
461static void find_h265(uint8_t *data, int len, TS_Indexer_t *indexer, TSParser *stream)
462{
463 TS_Indexer_Event_t event;
464 uint8_t *nalu = data;
465 size_t pes_data_len = len;
466 size_t nalu_len;
467
468 memset(&event, 0, sizeof(event));
469 event.pid = stream->pid;
470 event.offset = stream->offset;
471
472 while (nalu != NULL) {
473 int left = pes_data_len - (nalu - data);
474 if (left <= 4) {
475 memcpy(&stream->PES.data[0], nalu, left);
476 stream->PES.len = left;
477 break;
478 }
479
Yahui Hana082ab62023-07-14 14:41:39 +0800480 nalu = get_nalu(nalu, left, &nalu_len, 1);
Gong Kefa504d72023-04-18 10:23:35 +0800481 if (nalu == NULL)
482 break;
483
Yahui Hana082ab62023-07-14 14:41:39 +0800484 if (nalu[0] == 0x00 && nalu[1] == 0x00 && nalu[2] == 0x00 && nalu[3] == 0x01) {
485 int nalu_type = (nalu[4] & 0x7E) >> 1;
Gong Kefa504d72023-04-18 10:23:35 +0800486 //INF("nalu[3]: %#x, nalu_type: %#x\n", nalu[3], nalu_type);
Yahui Han63de7082023-07-12 18:30:10 +0800487 switch (nalu_type) {
488 case HEVC_NALU_BLA_W_LP:
489 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_LP;
490 break;
491
492 case HEVC_NALU_BLA_W_RADL:
493 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_RADL;
494 break;
495
Yahui Hana082ab62023-07-14 14:41:39 +0800496 case HEVC_NALU_BLA_N_LP:
497 event.type = TS_INDEXER_EVENT_TYPE_HEVC_BLA_N_LP;
498 break;
499
Yahui Han63de7082023-07-12 18:30:10 +0800500 case HEVC_NALU_IDR_W_RADL:
501 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_W_RADL;
502 //INF("HEVC I-frame found\n");
503 break;
504
505 case HEVC_NALU_IDR_N_LP:
506 event.type = TS_INDEXER_EVENT_TYPE_HEVC_IDR_N_LP;
507 break;
508
509 case HEVC_NALU_TRAIL_CRA:
510 event.type = TS_INDEXER_EVENT_TYPE_HEVC_TRAIL_CRA;
511 break;
512
513 case HEVC_NALU_SPS:
514 event.type = TS_INDEXER_EVENT_TYPE_HEVC_SPS;
515 break;
516
517 case HEVC_NALU_AUD:
518 event.type = TS_INDEXER_EVENT_TYPE_HEVC_AUD;
519 break;
520
521 default:
522 nalu += nalu_len;
523 continue;
524 }
525
526 event.pts = stream->PES.pts;
527 if (indexer->callback) {
528 indexer->callback(indexer, &event);
Gong Kefa504d72023-04-18 10:23:35 +0800529 }
530 }
531
532 nalu += nalu_len;
533 }
Yahui Han63de7082023-07-12 18:30:10 +0800534
Gong Kefa504d72023-04-18 10:23:35 +0800535 stream->PES.len = 0;
536}
537
538/*Parse the PES packet*/
539static void
540pes_packet(TS_Indexer_t *ts_indexer, uint8_t *data, int len, TSParser *stream)
541{
542 uint8_t *p = data;
543 TS_Indexer_t *pi = ts_indexer;
544 int left = len;
545 TS_Indexer_Event_t event;
546
547 memset(&event, 0, sizeof(event));
548 event.pid = stream->pid;
549 event.offset = stream->offset;
550
551 INF("stream: %p, state: %d\n", stream, stream->PES.state);
552 if (stream->PES.state <= TS_INDEXER_STATE_INIT) {
553 INF("%s, invalid state\n", __func__);
554 stream->PES.len = 0;
555 return;
556 }
557
558 /* needs splice two pieces of data together if have cache data */
559 if (stream->PES.len > 0) {
560 INF("%s have cache data %d bytes\n", __func__, stream->PES.len);
561 memcpy(&stream->PES.data[stream->PES.len], data, len);
562 p = &stream->PES.data[0];
563 left = stream->PES.len + len;
564 stream->PES.len = left;
565 }
566
567 if (stream->PES.state == TS_INDEXER_STATE_TS_START) {
568 /* needs cache data if no enough data to parse PES header */
569 if (left < 6) {
570 if (stream->PES.len <= 0) {
571 memcpy(&stream->PES.data[0], p, left);
572 stream->PES.len = left;
573 }
574 INF("not enough ts payload len: %#x\n", left);
575 return;
576 }
577
578 // chect the PES packet start code prefix
579 if ((p[0] != 0) || (p[1] != 0) || (p[2] != 1)) {
580 stream->PES.len = 0;
581 stream->PES.state = TS_INDEXER_STATE_INIT;
582 INF("%s, not the expected start code!\n", __func__);
583 return;
584 }
585
586 p += 6;
587 left -= 6;
588 stream->PES.state = TS_INDEXER_STATE_PES_HEADER;
589 }
590
591 if (stream->PES.state == TS_INDEXER_STATE_PES_HEADER) {
592 if (left < 8) {
593 if (stream->PES.len <= 0) {
594 memcpy(&stream->PES.data[0], p, left);
595 stream->PES.len = left;
596 }
597 INF("not enough optional pes header len: %#x\n", left);
598 return;
599 }
600
601 int header_length = p[2];
602 if (p[1] & 0x80) {
603 // parser pts
604 p += 3;
605 left -= 3;
606 event.pts = stream->PES.pts = (((uint64_t)(p[0] & 0x0E) << 29) |
607 ((uint64_t)p[1] << 22) |
608 ((uint64_t)(p[2] & 0xFE) << 14) |
609 ((uint64_t)p[3] << 7) |
610 (((uint64_t)p[4] & 0xFE) >> 1));
611 INF("pts: %lx, pos:%lx\n", event.pts, event.offset);
612
613 if (stream == &pi->video_parser) {
614 event.type = TS_INDEXER_EVENT_TYPE_VIDEO_PTS;
615 } else {
616 event.type = TS_INDEXER_EVENT_TYPE_AUDIO_PTS;
617 }
618 if (pi->callback) {
619 pi->callback(pi, &event);
620 }
621 }
Yahui Han63de7082023-07-12 18:30:10 +0800622 if (stream->format != -1) {
623 stream->PES.state = TS_INDEXER_STATE_PES_PTS;
Gong Kefa504d72023-04-18 10:23:35 +0800624
Yahui Han63de7082023-07-12 18:30:10 +0800625 p += header_length;
626 left -= header_length;
627 } else {
628 stream->PES.state = TS_INDEXER_STATE_INIT;
629 left = 0;
630 }
Gong Kefa504d72023-04-18 10:23:35 +0800631 }
632
633 stream->PES.len = left;
634 if (left <= 0
635 || stream->PES.state < TS_INDEXER_STATE_PES_PTS) {
636 return;
637 }
638
639 INF("stream->format: %d, left: %d\n", stream->format, left);
640 switch (stream->format) {
641 case TS_INDEXER_VIDEO_FORMAT_MPEG2:
642 find_mpeg(p, left, pi, &pi->video_parser);
643 break;
644
645 case TS_INDEXER_VIDEO_FORMAT_H264:
646 find_h264(p, left, pi, &pi->video_parser);
647 break;
648
649 case TS_INDEXER_VIDEO_FORMAT_HEVC:
650 find_h265(p, left, pi, &pi->video_parser);
651 break;
652
653 default:
Yahui Han63de7082023-07-12 18:30:10 +0800654 stream->PES.state = TS_INDEXER_STATE_INIT;
655 stream->PES.len = 0;
Gong Kefa504d72023-04-18 10:23:35 +0800656 break;
657 }
658}
659
660/*Parse the TS packet.*/
661static void
662ts_packet(TS_Indexer_t *ts_indexer, uint8_t *data)
663{
664 uint16_t pid;
665 uint8_t afc;
666 uint8_t *p = data;
667 TS_Indexer_t *pi = ts_indexer;
668 int len;
669 int is_start;
Yahui Han63de7082023-07-12 18:30:10 +0800670 TS_Indexer_Event_t event;
Gong Kefa504d72023-04-18 10:23:35 +0800671
672 is_start = p[1] & 0x40;
673 pid = ((p[1] & 0x1f) << 8) | p[2];
674 if (pid == 0x1fff)
675 return;
676
677 if ((pid != pi->video_parser.pid) &&
678 (pid != pi->audio_parser.pid)) {
679 return;
680 }
681
682 if (is_start) {
Yahui Han63de7082023-07-12 18:30:10 +0800683 memset(&event, 0, sizeof(event));
684 event.pid = pid;
685 event.offset = pi->offset;
686 event.type = TS_INDEXER_EVENT_TYPE_START_INDICATOR;
687 if (pi->callback) {
688 pi->callback(pi, &event);
689 }
690
Gong Kefa504d72023-04-18 10:23:35 +0800691 if (pid == pi->video_parser.pid) {
692 pi->video_parser.offset = pi->offset;
693 pi->video_parser.PES.state = TS_INDEXER_STATE_TS_START;
694 }
695 else if (pid == pi->audio_parser.pid) {
696 pi->audio_parser.offset = pi->offset;
697 pi->audio_parser.PES.state = TS_INDEXER_STATE_TS_START;
698 }
699 }
700
701 afc = (p[3] >> 4) & 0x03;
702
703 p += 4;
704 len = 184;
705
706 if (afc & 2) {
707 int adp_field_len = p[0];
Yahui Han63de7082023-07-12 18:30:10 +0800708 if (p[1] & 0x80) {
709 memset(&event, 0, sizeof(event));
710 event.pid = pid;
711 event.offset = pi->offset;
712 event.type = TS_INDEXER_EVENT_TYPE_DISCONTINUITY_INDICATOR;
713 if (pi->callback) {
714 pi->callback(pi, &event);
715 }
716 }
Gong Kefa504d72023-04-18 10:23:35 +0800717 p++;
718 len--;
719
720 p += adp_field_len;
721 len -= adp_field_len;
722
723 if (len < 0) {
724 ERR("illegal adaption field length!");
725 return;
726 }
727 }
728
729 // has payload
730 if ((afc & 1) && (len > 0)) {
731 // parser pes packet
732 pes_packet(pi, p, len, (pid == pi->video_parser.pid) ? &pi->video_parser : &pi->audio_parser);
733 }
734}
735
736/**
737 * Parse the TS stream and generate the index data.
738 * \param ts_indexer The TS indexer.
739 * \param data The TS data.
740 * \param len The length of the TS data in bytes.
741 * \return The left TS data length of bytes.
742 */
743int
744ts_indexer_parse (TS_Indexer_t *ts_indexer, uint8_t *data, int len)
745{
746 uint8_t *p = data;
747 int left = len;
748
749 if (ts_indexer == NULL || data == NULL || len <= 0)
750 return -1;
751
752 while (left > 0) {
753 // find the sync byte
754 if (*p == 0x47) {
755 if (left < TS_PKT_SIZE) {
756 INF("%s data length may not be 188-byte aligned\n", __func__);
757 return left;
758 }
759
760 // parse one ts packet
761 ts_packet(ts_indexer, p);
762 p += TS_PKT_SIZE;
763 left -= TS_PKT_SIZE;
764 ts_indexer->offset += TS_PKT_SIZE;
765 } else {
766 p++;
767 left--;
768 ts_indexer->offset++;
769 }
770 }
771
772 return left;
773}