blob: 5aefc37439a9345919b6ee817bbab057c42deaf8 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/* $Id: demuxmpeg.c,v 1.4 2004/10/19 23:11:36 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
It may be used under the terms of the GNU General Public License. */
#include "hb.h"
/* Basic MPEG demuxer, only works with DVDs (2048 bytes packets) */
int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es )
{
hb_buffer_t * buf_es;
int pos;
pos = 0;
#define d (buf_ps->data)
/* pack_header */
if( d[pos] != 0 || d[pos+1] != 0 ||
d[pos+2] != 0x1 || d[pos+3] != 0xBA )
{
hb_log( "hb_demux_ps: not a PS packet (%02x%02x%02x%02x)",
d[pos], d[pos+1], d[pos+2], d[pos+3] );
return 0;
}
pos += 4; /* pack_start_code */
pos += 9; /* pack_header */
pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
/* system_header */
if( d[pos] == 0 && d[pos+1] == 0 &&
d[pos+2] == 0x1 && d[pos+3] == 0xBB )
{
int header_length;
pos += 4; /* system_header_start_code */
header_length = ( d[pos] << 8 ) + d[pos+1];
pos += 2 + header_length;
}
/* pes */
while( pos + 6 < buf_ps->size &&
d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 )
{
int id;
int pes_packet_length;
int pes_packet_end;
int pes_header_d_length;
int pes_header_end;
int has_pts;
int64_t pts = -1;
pos += 3; /* packet_start_code_prefix */
id = d[pos];
pos += 1;
pes_packet_length = ( d[pos] << 8 ) + d[pos+1];
pos += 2; /* pes_packet_length */
pes_packet_end = pos + pes_packet_length;
if( id != 0xE0 && id != 0xBD &&
( id & 0xC0 ) != 0xC0 )
{
/* Not interesting */
pos = pes_packet_end;
continue;
}
has_pts = ( ( d[pos+1] >> 6 ) & 0x2 ) ? 1 : 0;
pos += 2; /* Required headers */
pes_header_d_length = d[pos];
pos += 1;
pes_header_end = pos + pes_header_d_length;
if( has_pts )
{
pts = ( ( ( (uint64_t) d[pos] >> 1 ) & 0x7 ) << 30 ) +
( d[pos+1] << 22 ) +
( ( d[pos+2] >> 1 ) << 15 ) +
( d[pos+3] << 7 ) +
( d[pos+4] >> 1 );
}
pos = pes_header_end;
if( id == 0xBD )
{
id |= ( d[pos] << 8 );
if( ( id & 0xF0FF ) == 0x80BD ) /* A52 */
{
pos += 4;
}
else if( ( id & 0xE0FF ) == 0x20BD || /* SPU */
( id & 0xF0FF ) == 0xA0BD ) /* LPCM */
{
pos += 1;
}
}
/* Sanity check */
if( pos >= pes_packet_end )
{
pos = pes_packet_end;
continue;
}
/* Here we hit we ES payload */
buf_es = hb_buffer_init( pes_packet_end - pos );
buf_es->id = id;
buf_es->start = pts;
buf_es->new_chap = buf_ps->new_chap; // Consume a chapter break, and apply it to the ES.
buf_ps->new_chap = 0;
memcpy( buf_es->data, d + pos, pes_packet_end - pos );
hb_list_add( list_es, buf_es );
pos = pes_packet_end;
}
#undef d
return 1;
}
|