summaryrefslogtreecommitdiffstats
path: root/libmediafork/demuxmpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmediafork/demuxmpeg.c')
-rw-r--r--libmediafork/demuxmpeg.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/libmediafork/demuxmpeg.c b/libmediafork/demuxmpeg.c
new file mode 100644
index 000000000..54bef2b47
--- /dev/null
+++ b/libmediafork/demuxmpeg.c
@@ -0,0 +1,125 @@
+/* $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 "mediafork.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;
+ 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;
+}