/*****************************************************************************
* ps.h: Program Stream demuxer helper
*****************************************************************************
- * Copyright (C) 2004-2009 the VideoLAN team
+ * Copyright (C) 2004-2009 VLC authors and VideoLAN
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <assert.h>
}
/* From id fill i_skip and es_format_t */
-static inline int ps_track_fill( ps_track_t *tk, ps_psm_t *p_psm, int i_id )
+static inline int ps_track_fill( ps_track_t *tk, ps_psm_t *p_psm, int i_id, block_t *p_pkt )
{
tk->i_skip = 0;
tk->i_id = i_id;
- if( ( i_id&0xff00 ) == 0xbd00 )
+ if( ( i_id&0xff00 ) == 0xbd00 ) /* 0xBD00 -> 0xBDFF, Private Stream 1 */
{
- if( ( i_id&0xf8 ) == 0x88 || (i_id&0xf8) == 0x98 )
+ if( ( i_id&0xf8 ) == 0x88 || /* 0x88 -> 0x8f - Can be DTS-HD primary audio in evob */
+ ( i_id&0xf8 ) == 0x98 ) /* 0x98 -> 0x9f - Can be DTS-HD secondary audio in evob */
{
es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_DTS );
tk->i_skip = 4;
}
- else if( ( i_id&0xf0 ) == 0x80
- || (i_id&0xf0) == 0xc0 ) /* AC-3, Can also be used for DD+/E-AC-3 */
+ else if( ( i_id&0xf8 ) == 0x80 || /* 0x80 -> 0x87 */
+ ( i_id&0xf0 ) == 0xc0 ) /* 0xc0 -> 0xcf AC-3, Can also be DD+/E-AC3 in evob */
{
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_A52 );
+ bool b_eac3 = false;
+ if( ( i_id&0xf0 ) == 0xc0 && p_pkt && p_pkt->i_buffer > 8 )
+ {
+ unsigned i_start = 9 + p_pkt->p_buffer[8];
+ /* AC-3 marking, see vlc_a52_header_Parse */
+ if( p_pkt->p_buffer[i_start + 4] == 0x0b ||
+ p_pkt->p_buffer[i_start + 5] == 0x77 )
+ {
+ int bsid = p_pkt->p_buffer[i_start + 9] >> 3;
+ if( bsid > 10 )
+ b_eac3 = true;
+ }
+ }
+
+ es_format_Init( &tk->fmt, AUDIO_ES, b_eac3 ? VLC_CODEC_EAC3 : VLC_CODEC_A52 );
tk->i_skip = 4;
}
- else if( (i_id&0xf0) == 0xb0 )
+ else if( ( i_id&0xfc ) == 0x00 ) /* 0x00 -> 0x03 */
{
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MLP );
- /* FIXME / untested ... no known decoder (at least not in VLC/ffmpeg) */
+ es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_CVD );
}
- else if( ( i_id&0xe0 ) == 0x20 )
+ else if( ( i_id&0xff ) == 0x10 ) /* 0x10 */
{
- es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_SPU );
- tk->i_skip = 1;
+ es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_TELETEXT );
}
- else if( ( i_id&0xf0 ) == 0xa0 )
+ else if( ( i_id&0xe0 ) == 0x20 ) /* 0x20 -> 0x3f */
{
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_DVD_LPCM );
+ es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_SPU );
tk->i_skip = 1;
}
- else if( ( i_id&0xff ) == 0x70 )
+ else if( ( i_id&0xff ) == 0x70 ) /* 0x70 */
{
es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_OGT );
}
- else if( ( i_id&0xfc ) == 0x00 )
+ else if( ( i_id&0xf0 ) == 0xa0 ) /* 0xa0 -> 0xaf */
{
- es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_CVD );
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_DVD_LPCM );
+ tk->i_skip = 1;
}
- else if( ( i_id&0xff ) == 0x10 )
+ else if( ( i_id&0xf0 ) == 0xb0 ) /* 0xb0 -> 0xbf */
{
- es_format_Init( &tk->fmt, SPU_ES, VLC_CODEC_TELETEXT );
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_TRUEHD );
+ tk->i_skip = 5;
}
else
{
return VLC_EGENERIC;
}
}
- else if( (i_id&0xff00) == 0xfd00 )
+ else if( (i_id&0xff00) == 0xfd00 ) /* 0xFD00 -> 0xFDFF */
{
uint8_t i_sub_id = i_id & 0xff;
- if( i_sub_id >= 0x55 && i_sub_id <= 0x5f )
+ if( ( i_sub_id >= 0x55 && i_sub_id <= 0x5f ) || /* Can be primary VC-1 in evob */
+ ( i_sub_id >= 0x75 && i_sub_id <= 0x7f ) ) /* Secondary VC-1 */
{
es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_VC1 );
}
return VLC_EGENERIC;
}
}
- else if( (i_id&0xff00) == 0xa000 )
+ else if( (i_id&0xff00) == 0xa000 ) /* 0xA000 -> 0xA0FF */
{
uint8_t i_sub_id = i_id & 0x07;
if( i_sub_id == 0 )
es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
- if( (i_id&0xf0) == 0xe0 && i_type == 0x1b )
- {
- es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_H264 );
- }
- else if( (i_id&0xf0) == 0xe0 && i_type == 0x10 )
- {
- es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MP4V );
- }
- else if( (i_id&0xf0) == 0xe0 && i_type == 0x02 )
- {
- es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MPGV );
- }
- else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x0f )
- {
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MP4A );
- }
- else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x11 )
- {
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MP4A );
- }
- else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x03 )
- {
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MPGA );
- }
-
- if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xf0 ) == 0xe0 )
+ if( (i_id&0xf0) == 0xe0 ) /* 0xe0 -> 0xef */
{
- es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MPGV );
+ if( i_type == 0x1b )
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_H264 );
+ }
+ else if( i_type == 0x10 )
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MP4V );
+ }
+ else if( i_type == 0x01 ||
+ i_type == 0x02 )
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MPGV );
+ }
+ else if( i_id == 0xe2 || /* Primary H.264 in evob */
+ i_id == 0xe3 ) /* Seconday H.264 in evob */
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_H264 );
+ }
+ else if( tk->fmt.i_cat == UNKNOWN_ES )
+ {
+ es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_MPGV );
+ }
}
- else if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xe0 ) == 0xc0 )
+ else if( ( i_id&0xe0 ) == 0xc0 ) /* 0xc0 -> 0xdf */
{
- es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MPGA );
+ if( i_type == 0x03 ||
+ i_type == 0x04 )
+ {
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MPGA );
+ }
+ else if( i_type == 0x0f )
+ {
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MP4A );
+ }
+ else if( i_type == 0x11 )
+ {
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MP4A );
+ }
+ else if( tk->fmt.i_cat == UNKNOWN_ES )
+ {
+ es_format_Init( &tk->fmt, AUDIO_ES, VLC_CODEC_MPGA );
+ }
}
else if( tk->fmt.i_cat == UNKNOWN_ES ) return VLC_EGENERIC;
}
return p_pkt->p_buffer[3];
}
-/* return the size of the next packet
- * You need to give him at least 14 bytes (and it need to start as a
- * valid packet) It does not handle less than 6 bytes */
+/* return the size of the next packet */
static inline int ps_pkt_size( const uint8_t *p, int i_peek )
{
- assert( i_peek >= 6 );
- if( p[3] == 0xb9 && i_peek >= 4 )
+ if( unlikely(i_peek < 4) )
+ {
+ return -1;
+ }
+ else if( p[3] == 0xb9 )
{
return 4;
}
else if( p[3] == 0xba )
{
- if( (p[4] >> 6) == 0x01 && i_peek >= 14 )
+ if( i_peek >= 14 && (p[4] >> 6) == 0x01 )
{
return 14 + (p[13]&0x07);
}
- else if( (p[4] >> 4) == 0x02 && i_peek >= 12 )
+ else if( i_peek >= 12 && (p[4] >> 4) == 0x02 )
{
return 12;
}
if( !tk[i_tk].b_seen )
{
- if( !ps_track_fill( &tk[i_tk], p_psm, i_id ) )
+ if( !ps_track_fill( &tk[i_tk], p_psm, i_id, p_pkt ) )
{
tk[i_tk].b_seen = true;
}
{
int i_buffer = p_pkt->i_buffer;
uint8_t *p_buffer = p_pkt->p_buffer;
- int i_length, i_version, i_info_length, i_esm_length, i_es_base;
+ int i_length, i_version, i_info_length, i_es_base;
if( !p_psm || p_buffer[3] != 0xbc ) return VLC_EGENERIC;
i_length = (uint16_t)(p_buffer[4] << 8) + p_buffer[5] + 6;
if( i_length > i_buffer ) return VLC_EGENERIC;
- //i_current_next_indicator = (p_buffer[6] && 0x01);
- i_version = (p_buffer[6] && 0xf8);
+ //i_current_next_indicator = (p_buffer[6] & 0x01);
+ i_version = (p_buffer[6] & 0xf8);
if( p_psm->i_version == i_version ) return VLC_EGENERIC;
if( i_info_length + 10 > i_length ) return VLC_EGENERIC;
/* Elementary stream map */
- i_esm_length = (uint16_t)(p_buffer[ 10 + i_info_length ] << 8) +
- p_buffer[ 11 + i_info_length];
+ /* int i_esm_length = (uint16_t)(p_buffer[ 10 + i_info_length ] << 8) +
+ p_buffer[ 11 + i_info_length]; */
i_es_base = 12 + i_info_length;
while( i_es_base + 4 < i_length )
}
}
- tmp_es = realloc_or_free( p_psm->es, sizeof(ps_es_t *) * (p_psm->i_es+1) );
+ tmp_es = realloc( p_psm->es, sizeof(ps_es_t *) * (p_psm->i_es+1) );
if( tmp_es )
{
p_psm->es = tmp_es;
if( !tk[i].b_seen || !tk[i].es ) continue;
- if( ps_track_fill( &tk_tmp, p_psm, tk[i].i_id ) != VLC_SUCCESS )
+ if( ps_track_fill( &tk_tmp, p_psm, tk[i].i_id, p_pkt ) != VLC_SUCCESS )
continue;
if( tk_tmp.fmt.i_codec == tk[i].fmt.i_codec )
es_out_Del( out, tk[i].es );
es_format_Clean( &tk[i].fmt );
+ tk_tmp.b_seen = true;
tk[i] = tk_tmp;
- tk[i].b_seen = true;
tk[i].es = es_out_Add( out, &tk[i].fmt );
}