Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 1 | /** |
| 2 | * \page ts_indexer_test |
| 3 | * \section Introduction |
| 4 | * test code with ts_indexer_xxxxx APIs. |
| 5 | * It supports: |
| 6 | * \li parse pts/i-frame from MPEG2/H264/HEVC transport stream |
| 7 | * |
| 8 | * \section Usage |
| 9 | * |
| 10 | * \li ts: bitstream file path |
| 11 | * \li vpid: the pid of video bitstream with pts/i-frame |
| 12 | * \li vfmt: the video format |
| 13 | * \li apid: the pid of audio bitstream with pts |
| 14 | * |
| 15 | * |
| 16 | * parse pts/i-frame: |
| 17 | * \code |
| 18 | * ts_indexer_test [ts=] [vpid=] [vfmt=] [apid=] |
| 19 | * \endcode |
| 20 | * |
| 21 | * \endsection |
| 22 | */ |
| 23 | |
| 24 | #ifdef _FORTIFY_SOURCE |
| 25 | #undef _FORTIFY_SOURCE |
| 26 | #endif |
| 27 | |
| 28 | #include <stdio.h> |
| 29 | #include <stdlib.h> |
| 30 | #include <string.h> |
| 31 | #include "ts_indexer.h" |
| 32 | |
| 33 | #define INF(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) |
| 34 | #define ERR(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) |
| 35 | |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 36 | typedef struct |
| 37 | { |
| 38 | uint8_t *ptr; |
| 39 | uint64_t last_pts; |
| 40 | uint64_t last_offset; |
| 41 | FILE *dump_file; |
| 42 | } ts_indexer_ctl; |
| 43 | |
| 44 | static ts_indexer_ctl gControl; |
| 45 | |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 46 | static void ts_indexer_event_cb(TS_Indexer_t *ts_indexer, TS_Indexer_Event_t *event) |
| 47 | { |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 48 | int write_len; |
| 49 | |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 50 | if (ts_indexer == NULL || event == NULL) |
| 51 | return; |
| 52 | |
| 53 | switch (event->type) { |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 54 | case TS_INDEXER_EVENT_TYPE_MPEG2_I_FRAME: |
| 55 | #if 1 |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 56 | INF("pid: %#x ", event->pid); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 57 | INF("TS_INDEXER_EVENT_TYPE_I_FRAME, offset: %lx, pts: %lx\n", |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 58 | event->offset, event->pts); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 59 | #endif |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 60 | break; |
| 61 | |
| 62 | case TS_INDEXER_EVENT_TYPE_VIDEO_PTS: |
Yahui Han | 53b3c50 | 2023-08-04 10:36:58 +0800 | [diff] [blame^] | 63 | #if 1 |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 64 | INF("PID: %#x ", event->pid); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 65 | INF("TS_INDEXER_EVENT_TYPE_VIDEO_PTS, Offset: %lx, Lastoffset: %lx, Pts: %lx\n", |
| 66 | event->offset, gControl.last_offset, event->pts); |
| 67 | write_len = ts_indexer->offset - gControl.last_offset; |
| 68 | if (gControl.dump_file) { |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 69 | fwrite(gControl.ptr, 1, write_len, gControl.dump_file); |
| 70 | gControl.ptr += write_len; |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 71 | } |
| 72 | gControl.last_offset = ts_indexer->offset; |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 73 | #endif |
| 74 | break; |
| 75 | |
| 76 | case TS_INDEXER_EVENT_TYPE_AUDIO_PTS: |
| 77 | #if 0 |
| 78 | INF("PID: %#x ", event->pid); |
| 79 | INF("TS_INDEXER_EVENT_TYPE_AUDIO_PTS, Offset: %lx, Pts: %lx\n", |
| 80 | event->offset, event->pts); |
| 81 | #endif |
| 82 | break; |
| 83 | |
Yahui Han | a082ab6 | 2023-07-14 14:41:39 +0800 | [diff] [blame] | 84 | //case TS_INDEXER_EVENT_TYPE_START_INDICATOR: |
| 85 | //case TS_INDEXER_EVENT_TYPE_DISCONTINUITY_INDICATOR: |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 86 | case TS_INDEXER_EVENT_TYPE_MPEG2_P_FRAME: |
| 87 | case TS_INDEXER_EVENT_TYPE_MPEG2_B_FRAME: |
| 88 | case TS_INDEXER_EVENT_TYPE_MPEG2_SEQUENCE: |
| 89 | case TS_INDEXER_EVENT_TYPE_AVC_I_SLICE: |
| 90 | case TS_INDEXER_EVENT_TYPE_AVC_P_SLICE: |
| 91 | case TS_INDEXER_EVENT_TYPE_AVC_B_SLICE: |
| 92 | case TS_INDEXER_EVENT_TYPE_AVC_SI_SLICE: |
| 93 | case TS_INDEXER_EVENT_TYPE_AVC_SP_SLICE: |
| 94 | case TS_INDEXER_EVENT_TYPE_HEVC_SPS: |
| 95 | case TS_INDEXER_EVENT_TYPE_HEVC_AUD: |
| 96 | case TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_LP: |
| 97 | case TS_INDEXER_EVENT_TYPE_HEVC_BLA_W_RADL: |
| 98 | case TS_INDEXER_EVENT_TYPE_HEVC_IDR_W_RADL: |
| 99 | case TS_INDEXER_EVENT_TYPE_HEVC_IDR_N_LP: |
| 100 | case TS_INDEXER_EVENT_TYPE_HEVC_TRAIL_CRA: |
Yahui Han | 53b3c50 | 2023-08-04 10:36:58 +0800 | [diff] [blame^] | 101 | INF("type: %d, offset: %#lx\n", event->type, event->offset); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 102 | break; |
| 103 | |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 104 | default: |
| 105 | break; |
| 106 | } |
| 107 | |
| 108 | return; |
| 109 | } |
| 110 | |
| 111 | static char *help_vfmt = |
| 112 | "\n\t0:TS_INDEXER_VIDEO_FORMAT_MPEG2" /**< MPEG2 video.*/ |
| 113 | "\n\t1:TS_INDEXER_VIDEO_FORMAT_H264" /**< H264.*/ |
| 114 | "\n\t2:TS_INDEXER_VIDEO_FORMAT_HEVC"; /**<HEVC.*/ |
| 115 | |
| 116 | static void usage(int argc, char *argv[]) |
| 117 | { |
| 118 | INF("Usage: %s [ts=] [vpid=] [vfmt=] [apid=]\n", argv[0]); |
| 119 | INF("Usage: %s\n", help_vfmt); |
| 120 | } |
| 121 | |
| 122 | int main(int argc, char **argv) |
| 123 | { |
| 124 | int i; |
| 125 | char file[512]; |
| 126 | int vpid = 0x1fff; |
| 127 | int apid = 0x1fff; |
| 128 | int vfmt = -1; |
| 129 | TS_Indexer_t ts_indexer; |
| 130 | int block_size = 188*1024; |
| 131 | |
| 132 | memset(&file[0], 0, sizeof(file)); |
| 133 | for (i = 1; i < argc; i++) { |
| 134 | if (!strncmp(argv[i], "ts=", 3)) |
| 135 | sscanf(argv[i], "ts=%s", &file[0]); |
| 136 | else if (!strncmp(argv[i], "vpid=", 5)) |
| 137 | sscanf(argv[i], "vpid=%i", &vpid); |
| 138 | else if (!strncmp(argv[i], "vfmt=", 5)) |
| 139 | sscanf(argv[i], "vfmt=%i", &vfmt); |
| 140 | else if (!strncmp(argv[i], "apid=", 5)) |
| 141 | sscanf(argv[i], "apid=%i", &apid); |
| 142 | else if (!strncmp(argv[i], "help", 4)) { |
| 143 | usage(argc, argv); |
| 144 | exit(0); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | if (argc == 1 || |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 149 | (vpid == 0x1fff && apid == 0x1fff)) |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 150 | { |
| 151 | usage(argc, argv); |
| 152 | exit(0); |
| 153 | } |
| 154 | |
| 155 | memset(&ts_indexer, 0, sizeof(TS_Indexer_t)); |
| 156 | ts_indexer_init(&ts_indexer); |
| 157 | ts_indexer_set_video_pid(&ts_indexer, vpid); |
| 158 | ts_indexer_set_audio_pid(&ts_indexer, apid); |
| 159 | ts_indexer_set_video_format(&ts_indexer, vfmt); |
| 160 | ts_indexer_set_event_callback(&ts_indexer, ts_indexer_event_cb); |
| 161 | |
| 162 | FILE *f = fopen(file, "rb"); |
| 163 | if (f == NULL) { |
| 164 | ERR("open %s failed!\n", file); |
| 165 | return -1; |
| 166 | } |
| 167 | |
| 168 | uint8_t *data = malloc(block_size); |
| 169 | if (data == NULL) { |
| 170 | ERR("no heap memory!\n"); |
| 171 | return -1; |
| 172 | } |
| 173 | |
| 174 | size_t len = 0; |
| 175 | INF("vpid: %#x, vfmt: %d, apid:%#x\n", vpid, vfmt, apid); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 176 | memset(&gControl, 0, sizeof(ts_indexer_ctl)); |
| 177 | gControl.last_pts = -1; |
| 178 | gControl.last_offset = 0; |
| 179 | gControl.dump_file = fopen("./dump.ts", "wb+"); |
| 180 | if (gControl.dump_file == NULL) { |
| 181 | ERR("open dump file failed\n"); |
| 182 | return -1; |
| 183 | } |
| 184 | |
| 185 | INF("ptr: %p ~ %p\n", &data[0], &data[0] + block_size); |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 186 | while (1) { |
| 187 | len = fread(data, 1, block_size, f); |
| 188 | if (len <= 0) |
| 189 | break; |
| 190 | |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 191 | gControl.ptr = &data[0]; |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 192 | ts_indexer_parse(&ts_indexer, data, len); |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 193 | if (gControl.ptr - &data[0] < len) { |
| 194 | int left = len - (gControl.ptr - &data[0]); |
| 195 | fwrite(gControl.ptr, 1, left, gControl.dump_file); |
| 196 | gControl.last_offset += left; |
| 197 | } |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 198 | } |
Yahui Han | 63de708 | 2023-07-12 18:30:10 +0800 | [diff] [blame] | 199 | fflush(gControl.dump_file); |
| 200 | fclose(gControl.dump_file); |
Gong Ke | fa504d7 | 2023-04-18 10:23:35 +0800 | [diff] [blame] | 201 | |
| 202 | return 0; |
| 203 | } |