1 /*
2 * scan_pack.c
3 *
4 * Copyright (C) Thomas Oestreich - June 2001
5 *
6 * This file is part of transcode, a video stream processing tool
7 *
8 * transcode is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * transcode is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Make; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "transcode.h"
25 #include "ioaux.h"
26 #include "aux_pes.h"
27 #include "seqinfo.h"
28 #include "demuxer.h"
29 #include "packets.h"
30
31 /* ------------------------------------------------------------
32 *
33 * auxiliary routines
34 *
35 * ------------------------------------------------------------*/
36
37 static char *picture_structure_str[4] = {
38 "Invalid Picture Structure",
39 "Top field",
40 "Bottom field",
41 "Frame Picture"
42 };
43
_cmp_32_bits(char * buf,long x)44 static int _cmp_32_bits(char *buf, long x)
45 {
46
47 if(0) {
48 tc_log_msg(__FILE__, "MAGIC: 0x%02lx 0x%02lx 0x%02lx 0x%02lx", (x >> 24) & 0xff, ((x >> 16) & 0xff), ((x >> 8) & 0xff), ((x ) & 0xff));
49 tc_log_msg(__FILE__, " FILE: 0x%02x 0x%02x 0x%02x 0x%02x", buf[0] & 0xff, buf[1] & 0xff, buf[2] & 0xff, buf[3] & 0xff);
50 }
51
52 if ((buf[0]& 0xff) != ((x >> 24) & 0xff))
53 return 0;
54 if ((buf[1]& 0xff) != ((x >> 16) & 0xff))
55 return 0;
56 if ((buf[2] & 0xff)!= ((x >> 8) & 0xff))
57 return 0;
58 if ((buf[3]& 0xff) != ((x ) & 0xff))
59 return 0;
60
61 // OK found it
62 return 1;
63 }
64
65
_cmp_16_bits(char * buf,long x)66 static int _cmp_16_bits(char *buf, long x)
67 {
68 if(0) {
69 tc_log_msg(__FILE__, "MAGIC: 0x%02lx 0x%02lx 0x%02lx 0x%02lx %s", (x >> 24) & 0xff, ((x >> 16) & 0xff), ((x >> 8) & 0xff), ((x ) & 0xff), filetype(x));
70 tc_log_msg(__FILE__, " FILE: 0x%02x 0x%02x 0x%02x 0x%02x", buf[2] & 0xff, buf[3] & 0xff, buf[0] & 0xff, buf[1] & 0xff);
71 }
72
73 if ((uint8_t)buf[0] != ((x >> 8) & 0xff))
74 return 0;
75 if ((uint8_t)buf[1] != ((x ) & 0xff))
76 return 0;
77
78 // OK found it
79 return 1;
80 }
81
pack_scan_16(char * video,long magic)82 static int pack_scan_16(char *video, long magic)
83 {
84 int k, off = (video[VOB_PACKET_OFFSET] & 0xff) + VOB_PACKET_OFFSET + 1;
85
86 for(k=off; k<=VOB_PACKET_SIZE-2; ++k) {
87 if(_cmp_16_bits(video+k, magic)) return(k);
88 }// scan buffer
89 return(-1);
90 }
91
92
pack_scan_32(char * video,long magic)93 static int pack_scan_32(char *video, long magic)
94 {
95 int k, off = (video[VOB_PACKET_OFFSET] & 0xff) + VOB_PACKET_OFFSET + 1;
96
97 for(k=off; k<=VOB_PACKET_SIZE-4; ++k) {
98 if(_cmp_32_bits(video+k, magic)) return(k);
99 }// scan buffer
100 return(-1);
101 }
102
103 #if 0 // unused
104 static unsigned long read_ts(char *_s)
105 {
106
107 unsigned long pts;
108
109 char *buffer=_s;
110
111 unsigned int ptr=0;
112
113 pts = (buffer[ptr++] >> 1) & 7; //low 4 bits (7==1111)
114 pts <<= 15;
115 pts |= (stream_read_int16(&buffer[ptr]) >> 1);
116 ptr+=2;
117 pts <<= 15;
118 pts |= (stream_read_int16(&buffer[ptr]) >> 1);
119
120 return pts;
121 }
122 #endif
123
124 #define BUF_WARN_COUNT 20
125
probe_picext(uint8_t * buffer,size_t buflen)126 static int probe_picext(uint8_t *buffer, size_t buflen)
127 {
128
129 // static char *picture_structure_str[4] = {
130 // "Invalid Picture Structure",
131 // "Top field",
132 // "Bottom field",
133 // "Frame Picture"
134 //};
135 if(buflen < 3) {
136 #ifdef PROBE_DEBUG
137 static int buf_small_count = 0;
138 if(buf_small_count == 0
139 || (buf_small_count % BUF_WARN_COUNT) == 0) {
140 tc_log_warn(__FILE__, "not enough buffer to probe picture extension "
141 "(buflen=%lu) [happened at least %i times]",
142 (unsigned long)buflen, buf_small_count);
143 }
144 buf_small_count++;
145 #endif
146 return(-1); /* failed probe */
147 }
148 return(buffer[2] & 3);
149 }
150
probe_group(uint8_t * buffer,size_t buflen)151 static const char *probe_group(uint8_t *buffer, size_t buflen)
152 {
153 static char retbuf[32];
154 if(buflen < 5) {
155 #ifdef PROBE_DEBUG
156 static int buf_small_count = 0;
157 if(buf_small_count == 0
158 || (buf_small_count % BUF_WARN_COUNT) == 0) {
159 tc_log_warn(__FILE__, "not enough buffer to probe picture group "
160 "(buflen=%lu) [happened at least %i times]",
161 (unsigned long)buflen, buf_small_count);
162 }
163 buf_small_count++;
164 #endif
165 *retbuf = 0;
166 } else {
167 tc_snprintf(retbuf, sizeof(retbuf), "%s%s",
168 (buffer[4] & 0x40) ? " closed_gop" : "",
169 (buffer[4] & 0x20) ? " broken_link" : "");
170 }
171 return retbuf;
172 }
173
174 int flag1=0, flag2=0, flag3=0;
175
scan_pack_pics(char * video)176 int scan_pack_pics(char *video)
177 {
178
179 int k, off = (video[VOB_PACKET_OFFSET] & 0xff) + VOB_PACKET_OFFSET + 1;
180
181 int ctr=0;
182
183
184 if(flag1) if( (video[off] & 0xff) == 0) ++ctr;
185 if(flag2) if( (video[off] & 0xff) == 1 && (video[off+1] & 0xff) == 0) ++ctr;
186 if(flag3) if( (video[off] & 0xff) == 0 && (video[off+1] & 0xff) == 1 && (video[off+2] & 0xff) == 0) ++ctr;
187
188 // tc_log_msg(__FILE__, "off=%d byte=0x%x byte=0x%x ctr=%d", off , (video[off] & 0xff), (video[VOB_PACKET_SIZE-4] & 0xff), ctr);
189
190 if(ctr && (verbose & TC_PRIVATE)) tc_log_msg(__FILE__, "split PIC code detected");
191
192 flag1=flag2=flag3=0;
193
194 for(k=off; k<=VOB_PACKET_SIZE-4; ++k) {
195 if(_cmp_32_bits(video+k, MPEG_PICTURE_START_CODE)) ++ctr;
196 }
197
198 if( (video[VOB_PACKET_SIZE-1] & 0xff) == 0) flag3=1;
199 if( (video[VOB_PACKET_SIZE-2] & 0xff) == 0 && (video[VOB_PACKET_SIZE-1] & 0xff) == 0) flag2=1;
200 if( (video[VOB_PACKET_SIZE-3] & 0xff) == 0 && (video[VOB_PACKET_SIZE-2] & 0xff) == 0 && (video[VOB_PACKET_SIZE-1] & 0xff) == 1) flag1=1;
201
202 // tc_log_msg(__FILE__, "ctr= %d | f1=%d, f2=%d, f3=%d", ctr, flag1, flag2, flag3);
203
204 return(ctr);
205 }
206
scan_pack_ext(char * buf)207 int scan_pack_ext(char *buf)
208 {
209
210 int n, ret_code=-1;
211
212 for(n=0; n<VOB_PACKET_SIZE-4; ++n) {
213
214 if(_cmp_32_bits(buf+n, TC_MAGIC_PICEXT) && ((uint8_t) buf[n+4]>>4)==8){
215 ret_code = probe_picext(buf+n+4, VOB_PACKET_SIZE-4-n);
216 }
217 } // probe extension header
218
219 return(ret_code);
220 }
221
222
scan_pack_payload(char * video,size_t size,int n,int verbose)223 void scan_pack_payload(char *video, size_t size, int n, int verbose)
224 {
225
226 int k;
227 char buf[256];
228 unsigned long i_pts, i_dts;
229
230 int aud_tag, vid_tag;
231
232 int len;
233
234 double pts;
235
236 seq_info_t si;
237
238 // scan payload
239
240 // time stamp:
241 ac_memcpy(buf, &video[4], 6);
242 pts = read_time_stamp(buf);
243
244 // tc_log_msg(__FILE__, "PTS=%ld %d %f %ld", read_time_stamp_long(buf),read_ts(buf), read_ts(buf)/90000., parse_pts(buf, 2));
245
246 // payload length
247 len = stream_read_int16(&video[18]);
248
249 tc_log_msg(__FILE__, "[%06d] id=0x%x SCR=%12.8f size=%4d", n, (video[17] & 0xff), pts, len);
250
251
252 if((video[17] & 0xff) == P_ID_MPEG) {
253
254 if((k=pack_scan_32(video, TC_MAGIC_M2V))!=-1) {
255
256 tc_log_msg(__FILE__, " MPEG SEQ start code found in packet %d, offset %4d", n, k);
257
258
259 //read packet header
260 ac_memcpy(buf, &video[20], 16);
261 get_pts_dts(buf, &i_pts, &i_dts);
262
263 tc_log_msg(__FILE__, " PTS=%f DTS=%f", (double) i_pts / 90000., (double) i_dts / 90000.);
264
265 stats_sequence(&video[k+4], &si);
266
267 }
268
269 if((k=pack_scan_32(video, MPEG_SEQUENCE_END_CODE))!=-1)
270 tc_log_msg(__FILE__, " MPEG SEQ end code found in packet %d, offset %4d", n, k);
271
272 if((k=pack_scan_32(video, MPEG_EXT_START_CODE))!=-1) {
273
274 if(((uint8_t)video[k+4]>>4)==8) {
275 int mode = probe_picext(&video[k+4], size - (size_t)k);
276 if(mode > 0)
277 tc_log_msg(__FILE__, " MPEG EXT start code found in packet %d, offset %4d, %s", n, k, picture_structure_str[mode]);
278 else
279 tc_log_msg(__FILE__, " MPEG EXT start code found INCOMPLETE in packet %d, offset %4d", n, k);
280 } else
281 tc_log_msg(__FILE__, " MPEG EXT start code found in packet %d, offset %4d", n, k);
282 }
283
284 if((k=pack_scan_32(video, MPEG_GOP_START_CODE))!=-1) {
285 tc_log_msg(__FILE__, " MPEG GOP start code found in packet %d, offset %4d, gop [%03d]%s",
286 n, k, gop_cnt,
287 probe_group((uint8_t*) &video[k+4], size - (size_t)k));
288 gop_pts=pts;
289 ++gop_cnt;
290 gop=1;
291 }
292
293 if((k=pack_scan_32(video, MPEG_PICTURE_START_CODE))!=-1)
294 tc_log_msg(__FILE__, " MPEG PIC start code found in packet %d, offset %4d", n, k);
295
296 if((k=pack_scan_32(video, MPEG_SYSTEM_START_CODE))!=-1)
297 tc_log_msg(__FILE__, " MPEG SYS start code found in packet %d, offset %4d", n, k);
298
299 if((k=pack_scan_32(video, MPEG_PADDING_START_CODE))!=-1)
300 tc_log_msg(__FILE__, " MPEG PAD start code found in packet %d, offset %4d", n, k);
301 }
302
303 if((video[17] & 0xff) == P_ID_AC3) {
304
305 //position of track code
306 uint8_t *ibuf=video+14;
307 uint8_t *tmp=ibuf + 9 + ibuf[8];
308
309 //read packet header
310 ac_memcpy(buf, &video[20], 16);
311 get_pts_dts(buf, &i_pts, &i_dts);
312
313 tc_log_msg(__FILE__, " substream PTS=%f [0x%x]", (double) i_pts / 90000., *tmp);
314
315 if((k=pack_scan_16(video, TC_MAGIC_AC3))!=-1) {
316 if(gop) {
317
318 tc_log_msg(__FILE__, " AC3 sync frame, packet %6d, offset %3d, gop [%03d], A-V %.3f", n, k, gop_cnt-1, pts-gop_pts);
319 gop=0;
320
321 } else
322 tc_log_msg(__FILE__, " AC3 sync frame found in packet %d, offset %d", n, k);
323 }
324
325 if((k=pack_scan_32(video, MPEG_PADDING_START_CODE))!=-1)
326 tc_log_msg(__FILE__, " MPEG PAD start code found in packet %d, offset %4d", n, k);
327
328 }
329
330 if((video[17] & 0xff) >= 0xc0 && (video[17] & 0xff) <= 0xdf) {
331
332 //read packet header
333 ac_memcpy(buf, &video[20], 16);
334 get_pts_dts(buf, &i_pts, &i_dts);
335
336 tc_log_msg(__FILE__, " MPEG audio PTS=%f [0x%x]", (double) i_pts / 90000., (video[17] & 0xff));
337 }
338
339 if((video[17] & 0xff) == P_ID_PROG) {
340
341 aud_tag = (video[23]>>2) & 0x3f;
342 vid_tag = video[24] & 0x1f;
343
344 tc_log_msg(__FILE__, " MPEG PRG start code found in packet %d, A=%d, V=%d", n, aud_tag, vid_tag);
345
346 }// check for sync packet
347
348 return;
349 }
350
scan_pack_header(char * buf,long x)351 int scan_pack_header(char *buf, long x)
352 {
353
354 int ret = _cmp_32_bits(buf, x);
355 if(0) tc_log_msg(__FILE__, "scan_pack_header() ret=%d", ret);
356 return(ret);
357 }
358