Commit 6f67ff83 authored by Laurent Aimar's avatar Laurent Aimar

* cinepak: add a new fourcc

 * ffmpeg and mp4: some clean up and change the way ffmpeg is
initialised.
parent d5eeda89
......@@ -2,7 +2,7 @@
* cinepak.c: cinepak video decoder
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: cinepak.c,v 1.3 2002/07/23 00:39:16 sam Exp $
* $Id: cinepak.c,v 1.4 2002/07/23 17:19:02 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -92,7 +92,14 @@ MODULE_DEACTIVATE_STOP
*****************************************************************************/
static int decoder_Probe( vlc_fourcc_t *pi_type )
{
return( ( *pi_type == VLC_FOURCC('c','v','i','d') ) ? 0 : -1 );
switch( *pi_type )
{
case( VLC_FOURCC('c','v','i','d') ):
case( VLC_FOURCC('C','V','I','D') ):
return( 0);
default:
return( -1 );
}
}
/*****************************************************************************
......
......@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.19 2002/07/23 00:39:17 sam Exp $
* $Id: ffmpeg.c,v 1.20 2002/07/23 17:19:02 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -174,19 +174,33 @@ static int decoder_Run ( decoder_fifo_t * p_fifo )
( *(u8*)(p) + ( *((u8*)(p)+1) << 8 ) + \
( *((u8*)(p)+2) << 16 ) + ( *((u8*)(p)+3) << 24 ) )
static void __ParseBitMapInfoHeader( bitmapinfoheader_t *h, byte_t *p_data )
static void ffmpeg_ParseBitMapInfoHeader( bitmapinfoheader_t *p_bh,
u8 *p_data )
{
h->i_size = GetDWLE( p_data );
h->i_width = GetDWLE( p_data + 4 );
h->i_height = GetDWLE( p_data + 8 );
h->i_planes = GetWLE( p_data + 12 );
h->i_bitcount = GetWLE( p_data + 14 );
h->i_compression = GetDWLE( p_data + 16 );
h->i_sizeimage = GetDWLE( p_data + 20 );
h->i_xpelspermeter = GetDWLE( p_data + 24 );
h->i_ypelspermeter = GetDWLE( p_data + 28 );
h->i_clrused = GetDWLE( p_data + 32 );
h->i_clrimportant = GetDWLE( p_data + 36 );
p_bh->i_size = GetDWLE( p_data );
p_bh->i_width = GetDWLE( p_data + 4 );
p_bh->i_height = GetDWLE( p_data + 8 );
p_bh->i_planes = GetWLE( p_data + 12 );
p_bh->i_bitcount = GetWLE( p_data + 14 );
p_bh->i_compression = GetDWLE( p_data + 16 );
p_bh->i_sizeimage = GetDWLE( p_data + 20 );
p_bh->i_xpelspermeter = GetDWLE( p_data + 24 );
p_bh->i_ypelspermeter = GetDWLE( p_data + 28 );
p_bh->i_clrused = GetDWLE( p_data + 32 );
p_bh->i_clrimportant = GetDWLE( p_data + 36 );
if( p_bh->i_size > 40 )
{
p_bh->i_data = p_bh->i_size - 40;
p_bh->p_data = malloc( p_bh->i_data );
memcpy( p_bh->p_data, p_data + 40, p_bh->i_data );
}
else
{
p_bh->i_data = 0;
p_bh->p_data = NULL;
}
}
/* get the first pes from fifo */
static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
......@@ -423,89 +437,6 @@ static vout_thread_t *ffmpeg_CreateVout( videodec_thread_t *p_vdec,
return( p_vout );
}
#if 0
/* segfault some^Wevery times*/
static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
AVPicture *p_avpicture,
videodec_thread_t *p_vdec )
{
int i_plane;
int i_x, i_y;
int i_x_max, i_y_max;
int i_width;
int i_height;
int i_dst_stride;
int i_src_stride;
u8 *p_dest;
u8 *p_src;
i_width = p_vdec->p_context->width;
i_height= p_vdec->p_context->height;
p_dest = p_pic->p[0].p_pixels;
p_src = p_avpicture->data[0];
i_src_stride = p_avpicture->linesize[0];
i_dst_stride = p_pic->p[0].i_pitch;
if( i_src_stride == i_dst_stride )
{
p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_src_stride * i_height );
}
else
{
for( i_y = 0; i_y < i_height; i_y++ )
{
p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_width );
p_dest += i_dst_stride;
p_src += i_src_stride;
}
}
for( i_plane = 1; i_plane < 3; i_plane++ )
{
i_y_max = p_pic->p[i_plane].i_lines;
p_src = p_avpicture->data[i_plane];
p_dest = p_pic->p[i_plane].p_pixels;
i_dst_stride = p_pic->p[i_plane].i_pitch;
i_src_stride = p_avpicture->linesize[i_plane];
i_x_max = __MIN( i_dst_stride / 2, i_src_stride );
for( i_y = 0; i_y <( i_y_max + 1 ) / 2 ; i_y++ )
{
for( i_x = 0; i_x < i_x_max - 1; i_x++ )
{
p_dest[2 * i_x ] = p_src[i_x];
p_dest[2 * i_x + 1] = ( p_src[i_x] + p_src[i_x + 1] ) / 2;
}
p_dest[2 * i_x_max - 2] = p_src[i_x];
p_dest[2 * i_x_max - 1] = p_src[i_x];
p_dest += 2 * i_dst_stride;
p_src += i_src_stride;
}
p_src = p_pic->p[i_plane].p_pixels;
p_dest = p_src + i_dst_stride;
for( i_y = 0; i_y < ( i_y_max + 1 ) / 2 ; i_y++ )
{
p_vdec->p_fifo->p_vlc->pf_memcpy( p_dest, p_src, i_dst_stride );
p_dest += 2*i_dst_stride;
p_src += 2*i_dst_stride;
}
}
}
#endif
/* FIXME FIXME FIXME this is a big shit
does someone want to rewrite this function ?
or said to me how write a better thing
......@@ -679,8 +610,8 @@ static int InitThread( videodec_thread_t *p_vdec )
if( p_vdec->p_fifo->p_demux_data )
{
__ParseBitMapInfoHeader( &p_vdec->format,
(byte_t*)p_vdec->p_fifo->p_demux_data );
ffmpeg_ParseBitMapInfoHeader( &p_vdec->format,
(u8*)p_vdec->p_fifo->p_demux_data );
}
else
{
......@@ -755,10 +686,29 @@ static int InitThread( videodec_thread_t *p_vdec )
msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
p_vdec->psz_namecodec );
}
/* first give init data */
if( p_vdec->format.i_data )
{
AVPicture avpicture;
int b_gotpicture;
switch( i_ffmpeg_codec )
{
case( CODEC_ID_MPEG4 ):
avcodec_decode_video( p_vdec->p_context, &avpicture,
&b_gotpicture,
p_vdec->format.p_data,
p_vdec->format.i_data );
break;
default:
break;
}
}
/* This will be created after the first decoded frame */
p_vdec->p_vout = NULL;
return( 0 );
}
......@@ -921,6 +871,11 @@ static void EndThread( videodec_thread_t *p_vdec )
vlc_object_detach( p_vdec->p_vout, p_vdec->p_fifo );
vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
}
if( p_vdec->format.p_data != NULL)
{
free( p_vdec->format.p_data );
}
free( p_vdec );
}
......@@ -2,7 +2,7 @@
* ffmpeg_vdec.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: ffmpeg.h,v 1.7 2002/07/23 00:39:17 sam Exp $
* $Id: ffmpeg.h,v 1.8 2002/07/23 17:19:02 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -35,6 +35,10 @@ typedef struct bitmapinfoheader_s
u32 i_ypelspermeter;
u32 i_clrused;
u32 i_clrimportant;
int i_data;
u8 *p_data;
} bitmapinfoheader_t;
/* MPEG4 video */
......
......@@ -2,7 +2,7 @@
* libmp4.c : LibMP4 library for mp4 module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: libmp4.c,v 1.4 2002/07/23 00:39:17 sam Exp $
* $Id: libmp4.c,v 1.5 2002/07/23 17:19:02 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
......@@ -1208,6 +1208,9 @@ int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratehi );
MP4_GET2BYTES( p_box->data.p_sample_soun->i_sampleratelo );
MP4_SeekStream( p_stream, p_box->i_pos + MP4_BOX_HEADERSIZE( p_box ) + 28 );
MP4_ReadBoxContainerRaw( p_stream, p_box ); /* esds */
#ifdef MP4_VERBOSE
msg_Dbg( p_stream->p_input, "Read Box: \"soun\" in stsd channel %d sample size %d sampl rate %f",
p_box->data.p_sample_soun->i_channelcount,
......@@ -1219,6 +1222,7 @@ int MP4_ReadBox_sample_soun( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
MP4_READBOX_EXIT( 1 );
}
#if 0
int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
{
int i;
......@@ -1257,6 +1261,7 @@ int MP4_ReadBox_sample_mp4a( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
#endif
MP4_READBOX_EXIT( 1 );
}
#endif
int MP4_ReadBox_sample_vide( MP4_Stream_t *p_stream, MP4_Box_t *p_box )
{
......@@ -1991,7 +1996,7 @@ static struct
/* for codecs */
{ FOURCC_soun, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
{ FOURCC__mp3, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
{ FOURCC_mp4a, MP4_ReadBox_sample_mp4a, MP4_FreeBox_Common },
{ FOURCC_mp4a, MP4_ReadBox_sample_soun, MP4_FreeBox_Common },
{ FOURCC_vide, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
{ FOURCC_mp4v, MP4_ReadBox_sample_vide, MP4_FreeBox_Common },
......
......@@ -2,7 +2,7 @@
* libmp4.h : LibMP4 library for mp4 module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: libmp4.h,v 1.4 2002/07/23 00:39:17 sam Exp $
* $Id: libmp4.h,v 1.5 2002/07/23 17:19:02 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
......@@ -321,22 +321,6 @@ typedef struct MP4_Box_data_sample_soun_s
} MP4_Box_data_sample_soun_t;
typedef struct MP4_Box_data_sample_mp4a_s
{
u8 i_reserved1[6];
u16 i_data_reference_index;
u32 i_reserved2[2];
u16 i_channelcount;
u16 i_samplesize;
u16 i_predefined;
u16 i_reserved3;
u16 i_sampleratehi; /* timescale of track */
u16 i_sampleratelo;
} MP4_Box_data_sample_mp4a_t;
typedef struct MP4_Box_data_sample_vide_s
{
u8 i_reserved1[6];
......@@ -362,34 +346,6 @@ typedef struct MP4_Box_data_sample_vide_s
} MP4_Box_data_sample_vide_t;
/*
typedef struct MP4_Box_data_sample_mp4v_s
{
u8 i_reserved1[6];
u16 i_data_reference_index;
u16 i_predefined1;
u16 i_reserved2;
u32 i_predefined2[3];
s16 i_width;
s16 i_height;
u32 i_horizresolution;
u32 i_vertresolution;
u32 i_reserved3;
u16 i_predefined3;
u8 i_compressorname[32];
s16 i_depth;
s16 i_predefined4;
} MP4_Box_data_sample_mp4v_t;
*/
typedef struct MP4_Box_data_sample_hint_s
{
u8 i_reserved1[6];
......@@ -648,9 +604,7 @@ typedef union MP4_Box_data_s
MP4_Box_data_ctts_t *p_ctts;
MP4_Box_data_stsd_t *p_stsd;
MP4_Box_data_sample_vide_t *p_sample_vide;
MP4_Box_data_sample_vide_t *p_sample_mp4v;
MP4_Box_data_sample_soun_t *p_sample_soun;
MP4_Box_data_sample_soun_t *p_sample_mp4a;
MP4_Box_data_sample_hint_t *p_sample_hint;
MP4_Box_data_esds_t *p_esds;
......
......@@ -2,7 +2,7 @@
* mp4.c : MP4 file input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: mp4.c,v 1.5 2002/07/23 00:39:17 sam Exp $
* $Id: mp4.c,v 1.6 2002/07/23 17:19:02 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
......@@ -89,7 +89,7 @@ static int MP4_ReadSample();
static int MP4_DecodeSample();
#define MP4_Set4BytesLE( p, dw ) \
*((u8*)p) = ( dw&0xff ); \
*((u8*)p) = ( (dw)&0xff ); \
*((u8*)p+1) = ( ((dw)>> 8)&0xff ); \
*((u8*)p+2) = ( ((dw)>>16)&0xff ); \
*((u8*)p+3) = ( ((dw)>>24)&0xff )
......@@ -186,7 +186,11 @@ static int MP4Init( input_thread_t *p_input )
break;
default:
msg_Info( p_input,
"Unrecognize major file specification." );
"Unrecognize major file specification (%c%c%c%c).",
p_ftyp->data.p_ftyp->i_major_brand&0xff,
( p_ftyp->data.p_ftyp->i_major_brand >> 8)&0xff,
( p_ftyp->data.p_ftyp->i_major_brand >> 16 )&0xff,
( p_ftyp->data.p_ftyp->i_major_brand >> 24 )&0xff );
break;
}
}
......@@ -406,14 +410,7 @@ static void MP4End( input_thread_t *p_input )
FREE(p_demux->track[i_track].chunk[i_chunk].p_sample_delta_dts );
}
}
#if 0
/* if( p_demux->track->p_data_init )
{
input_DeletePacket( p_input->p_method_data,
p_demux->track->p_data_init );
}
*/
#endif
if( !p_demux->track[i_track].i_sample_size )
{
FREE( p_demux->track[i_track].p_sample_size );
......@@ -754,7 +751,11 @@ static void MP4_StartDecoder( input_thread_t *p_input,
MP4_Box_t *p_sample;
int i;
int i_chunk;
u8 *p_bmih;
int i_decoder_specific_info_len;
u8 *p_decoder_specific_info;
u8 *p_init;
MP4_Box_t *p_esds;
......@@ -772,20 +773,29 @@ static void MP4_StartDecoder( input_thread_t *p_input,
if( !p_demux_track->chunk[i_chunk].i_sample_description_index )
{
msg_Warn( p_input, "invalid SampleEntry index for this track i_cat %d" );
msg_Warn( p_input,
"invalid SampleEntry index (track ID 0x%x)",
p_demux_track->i_track_ID );
return;
}
p_sample = MP4_FindNbBox( p_demux_track->p_stsd,
p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
p_demux_track->chunk[i_chunk].i_sample_description_index - 1);
if( !p_sample )
if( ( !p_sample )||( !p_sample->data.p_data ) )
{
msg_Warn( p_input, "cannot find SampleEntry for this track" );
msg_Warn( p_input,
"cannot find SampleEntry (track ID 0x%x)",
p_demux_track->i_track_ID );
return;
}
if( !p_sample->data.p_data )
{
printf( "\nAhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh %.4s\n",
&p_sample->i_type );
return;
}
vlc_mutex_lock( &p_input->stream.stream_lock );
p_demux_track->p_es = input_AddES( p_input,
p_input->stream.p_selected_program,
......@@ -803,68 +813,149 @@ static void MP4_StartDecoder( input_thread_t *p_input,
p_demux_track->p_es->i_fourcc = p_sample->i_type;
p_demux_track->p_es->i_cat = p_demux_track->i_cat;
i_decoder_specific_info_len = 0;
p_decoder_specific_info = NULL;
/* now see if esds is present and if so create a data packet
with decoder_specific_info */
#define p_decconfig p_esds->data.p_esds->es_descriptor.p_decConfigDescr
if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )
&& p_decconfig && p_decconfig->i_decoder_specific_info_len )
if( ( p_esds = MP4_FindBox( p_sample, FOURCC_esds ) )&&
( p_esds->data.p_esds )&&
( p_decconfig ) )
{
data_packet_t *p_data;
int i_size = p_decconfig->i_decoder_specific_info_len;
/* data packet for the data */
if( !(p_data = input_NewPacket( p_input->p_method_data, i_size ) ) )
/* First update information based on i_objectTypeIndication */
switch( p_decconfig->i_objectTypeIndication )
{
return;
case( 0x20 ): /* MPEG4 VIDEO */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','v' );
break;
case( 0x40):
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
break;
case( 0x60):
case( 0x61):
case( 0x62):
case( 0x63):
case( 0x64):
case( 0x65): /* MPEG2 video */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
break;
/* Theses are MPEG2-AAC (what is this codec ?) */
case( 0x66): /* main profile */
case( 0x67): /* Low complexity profile */
case( 0x68): /* Scaleable Sampling rate profile */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','4','a' );
break;
/* true MPEG 2 audio */
case( 0x69):
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
break;
case( 0x6a): /* MPEG1 video */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
break;
case( 0x6b): /* MPEG1 audio */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
break;
case( 0x6c ): /* jpeg */
p_demux_track->p_es->i_fourcc = VLC_FOURCC( 'j','p','e','g' );
break;
default:
/* Unknown entry, but don't touch i_fourcc */
msg_Warn( p_input,
"objectTypeIndication(0x%x) unknow (Track ID 0x%x)",
p_decconfig->i_objectTypeIndication,
p_demux_track->i_track_ID );
break;
}
memcpy( p_data->p_payload_start,
p_decconfig->p_decoder_specific_info,
i_size );
p_demux_track->p_data_init = p_data;
i_decoder_specific_info_len =
p_decconfig->i_decoder_specific_info_len;
p_decoder_specific_info =
p_decconfig->p_decoder_specific_info;
}
#undef p_decconfig
/* some last initialisation */
/* XXX I create a bitmapinfoheader_t or
waveformatex_t for each stream, up to now it's the best thing
I've found but it could exist a better solution :) as something
like adding some new fields in p_es ...
XXX I don't set all values, only thoses that are interesting or known
--> bitmapinfoheader_t : width and height
--> waveformatex_t : channels, samplerate, bitspersample
and at the end I add p_decoder_specific_info
TODO set more values
*/
switch( p_demux_track->i_cat )
{
case( VIDEO_ES ):
/* now create a bitmapinfoheader_t for decoder */
p_bmih = malloc( 40 );
memset( p_bmih, 0, 40);
MP4_Set4BytesLE( p_bmih, 40 );
if( p_sample->data.p_sample_mp4v
&& p_sample->data.p_sample_mp4v->i_width )
/* now create a bitmapinfoheader_t for decoder and
add information found in p_esds */
p_init = malloc( 40 + i_decoder_specific_info_len);
memset( p_init, 0, 40 + i_decoder_specific_info_len);
MP4_Set4BytesLE( p_init, 40 + i_decoder_specific_info_len );
if( p_sample->data.p_sample_vide->i_width )
{
MP4_Set4BytesLE( p_bmih + 4,
p_sample->data.p_sample_mp4v->i_width );
MP4_Set4BytesLE( p_init + 4,
p_sample->data.p_sample_vide->i_width );
}
else
{
/* use display size */
MP4_Set4BytesLE( p_bmih + 4, p_demux_track->i_width );
MP4_Set4BytesLE( p_init + 4, p_demux_track->i_width );
}
if( p_sample->data.p_sample_mp4v
&& p_sample->data.p_sample_mp4v->i_height )
if( p_sample->data.p_sample_vide->i_height )
{
MP4_Set4BytesLE( p_bmih + 8,
p_sample->data.p_sample_mp4v->i_height );
MP4_Set4BytesLE( p_init + 8,
p_sample->data.p_sample_vide->i_height );
}
else
{
MP4_Set4BytesLE( p_bmih + 8, p_demux_track->i_height );
MP4_Set4BytesLE( p_init + 8, p_demux_track->i_height );
}
if( i_decoder_specific_info_len )
{
memcpy( p_init + 40,
p_decoder_specific_info,
i_decoder_specific_info_len);
}
p_demux_track->p_es->p_demux_data = p_bmih;
break;
case( AUDIO_ES ):
p_init = malloc( 18 + i_decoder_specific_info_len);
memset( p_init, 0, 18 + i_decoder_specific_info_len);
MP4_Set2BytesLE( p_init + 2, /* i_channel */
p_sample->data.p_sample_soun->i_channelcount );
MP4_Set4BytesLE( p_init + 4, /* samplepersec */
p_sample->data.p_sample_soun->i_sampleratehi );
MP4_Set4BytesLE( p_init + 8, /* avgbytespersec */
p_sample->data.p_sample_soun->i_channelcount *
p_sample->data.p_sample_soun->i_sampleratehi *
(p_sample->data.p_sample_soun->i_samplesize/8) );
MP4_Set2BytesLE( p_init + 14, /* bits/sample */
p_sample->data.p_sample_soun->i_samplesize );
MP4_Set2BytesLE( p_init + 16, /* i_size, specific info len*/
i_decoder_specific_info_len );
if( i_decoder_specific_info_len )
{
memcpy( p_init + 18,
p_decoder_specific_info,
i_decoder_specific_info_len);
}
break;
default:
p_init = NULL;
break;
}
p_demux_track->p_es->p_demux_data = p_init;
vlc_mutex_lock( &p_input->stream.stream_lock );
input_SelectES( p_input, p_demux_track->p_es );
vlc_mute