Commit 915759dc authored by Christophe Massiot's avatar Christophe Massiot

* Exploded the outdated generic decoder ;

* Updated ChangeLog and TODO.
parent 1a03af9a
...@@ -50,6 +50,13 @@ HEAD ...@@ -50,6 +50,13 @@ HEAD
* Put most builtins in plugins again due to performances issues. * Put most builtins in plugins again due to performances issues.
* Fixed the painfully slow build process (at last!). * Fixed the painfully slow build process (at last!).
* Added new dummy input plugin. * Added new dummy input plugin.
* Wrote an ES input plug-in for .mpg files which didn't work.
* Fixed a bug in GetChunk() for very small chunks of data (hence a bug
in the SPU decoder).
* Reactivated SDL parachute in non-debug mode (because of a memory
leakage).
* Added IDEALX developer documentation in doc/.
* Removed the outdated generic decoder.
0.2.80 0.2.80
Tue, 5 Jun 2001 04:41:06 +0200 Tue, 5 Jun 2001 04:41:06 +0200
......
...@@ -30,7 +30,6 @@ AC3_SPDIF := ac3_spdif ac3_iec958 ...@@ -30,7 +30,6 @@ AC3_SPDIF := ac3_spdif ac3_iec958
LPCM_DECODER := lpcm_decoder_thread LPCM_DECODER := lpcm_decoder_thread
AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math AUDIO_DECODER := audio_decoder adec_generic adec_layer1 adec_layer2 adec_math
SPU_DECODER := spu_decoder SPU_DECODER := spu_decoder
#GEN_DECODER := generic_decoder
VIDEO_PARSER := video_parser vpar_headers vpar_blocks vpar_synchro video_fifo VIDEO_PARSER := video_parser vpar_headers vpar_blocks vpar_synchro video_fifo
VIDEO_DECODER := video_decoder VIDEO_DECODER := video_decoder
MISC := mtime tests modules netutils MISC := mtime tests modules netutils
...@@ -44,7 +43,6 @@ C_OBJ := $(INTERFACE:%=src/interface/%.o) \ ...@@ -44,7 +43,6 @@ C_OBJ := $(INTERFACE:%=src/interface/%.o) \
$(LPCM_DECODER:%=src/lpcm_decoder/%.o) \ $(LPCM_DECODER:%=src/lpcm_decoder/%.o) \
$(AUDIO_DECODER:%=src/audio_decoder/%.o) \ $(AUDIO_DECODER:%=src/audio_decoder/%.o) \
$(SPU_DECODER:%=src/spu_decoder/%.o) \ $(SPU_DECODER:%=src/spu_decoder/%.o) \
$(GEN_DECODER:%=src/generic_decoder/%.o) \
$(VIDEO_PARSER:%=src/video_parser/%.o) \ $(VIDEO_PARSER:%=src/video_parser/%.o) \
$(VIDEO_DECODER:%=src/video_decoder/%.o) \ $(VIDEO_DECODER:%=src/video_decoder/%.o) \
$(MISC:%=src/misc/%.o) $(MISC:%=src/misc/%.o)
......
...@@ -144,7 +144,7 @@ Difficulty: Hard ...@@ -144,7 +144,7 @@ Difficulty: Hard
Urgency: Important Urgency: Important
Description: Write stream zones support Description: Write stream zones support
For random access we need to know where stream descriptors are valid For random access we need to know where stream descriptors are valid
and reside (essentially DVD plugin). -> Meuuh and reside (essentially DVD plugin).
Status: Done (stef) Status: Done (stef)
Task: 0x4d Task: 0x4d
...@@ -161,7 +161,7 @@ Description: Update documentation ...@@ -161,7 +161,7 @@ Description: Update documentation
The input structures have undergone a major restructuration with The input structures have undergone a major restructuration with
input-II. It might be a good idea to reflect thoses changes in the input-II. It might be a good idea to reflect thoses changes in the
documentation. documentation.
Status: Todo Status: Done 16 Jul 2001 (Meuuh)
Task: 0x4b Task: 0x4b
Difficulty: Guru Difficulty: Guru
...@@ -176,8 +176,7 @@ Difficulty: Medium ...@@ -176,8 +176,7 @@ Difficulty: Medium
Urgency: Normal Urgency: Normal
Description: Write ES input plugin Description: Write ES input plugin
We need to be able to read .mpg video streams, or .mp* audio streams. We need to be able to read .mpg video streams, or .mp* audio streams.
More information -> Meuuh Status: Done 27 Jun 2001 (Meuuh)
Status: Todo
Task: 0x49 Task: 0x49
Difficulty: Easy Difficulty: Easy
......
/*****************************************************************************
* generic_decoder.c : generic decoder thread
* This decoder provides a way to parse packets which do not belong to any
* known stream type, or to redirect packets to files. It can extract PES files
* from a multiplexed stream, identify automatically ES in a stream missing
* stream informations (i.e. a TS stream without PSI) and update ES tables in
* its input thread, or just print informations about what it receives in DEBUG
* mode.
* A single generic decoder is able to handle several ES, therefore it can be
* used as a 'default' decoder by the input thread.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: generic_decoder.c,v 1.18 2001/03/21 13:42:34 sam Exp $
*
* Authors: Vincent Seguin <seguin@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
* (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.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "threads.h"
#include "threads.h"
#include "intf_msg.h"
#include "debug.h"
#include "input.h"
#include "input_netlist.h"
#include "decoder_fifo.h"
#include "generic_decoder.h"
/*
* Local prototypes
*/
static int CheckConfiguration ( gdec_cfg_t *p_cfg );
static int InitThread ( gdec_thread_t *p_gdec );
static void RunThread ( gdec_thread_t *p_gdec );
static void ErrorThread ( gdec_thread_t *p_gdec );
static void EndThread ( gdec_thread_t *p_gdec );
static void IdentifyPES ( gdec_thread_t *p_gdec, pes_packet_t *p_pes,
int i_stream_id );
static void PrintPES ( pes_packet_t *p_pes, int i_stream_id );
/*****************************************************************************
* gdec_CreateThread: create a generic decoder thread
*****************************************************************************
* This function creates a new generic decoder thread, and returns a pointer
* to its description. On error, it returns NULL.
* Following configuration properties are used:
* GDEC_CFG_ACTIONS (required)
* XXX??
*****************************************************************************/
gdec_thread_t * gdec_CreateThread( gdec_cfg_t *p_cfg, input_thread_t *p_input,
int *pi_status )
{
gdec_thread_t * p_gdec; /* thread descriptor */
int i_status; /* thread status */
/*
* Check configuration
*/
if( CheckConfiguration( p_cfg ) )
{
return( NULL );
}
/* Allocate descriptor and initialize flags */
p_gdec = (gdec_thread_t *) malloc( sizeof(gdec_thread_t) );
if( p_gdec == NULL ) /* error */
{
return( NULL );
}
/* Copy configuration */
p_gdec->i_actions = p_cfg->i_actions;
/* XXX?? */
/* Set status */
p_gdec->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_gdec->pi_status = THREAD_CREATE;
/* Initialize flags */
p_gdec->b_die = 0;
p_gdec->b_error = 0;
p_gdec->b_active = 1;
/* Create thread */
if( vlc_thread_create( &p_gdec->thread_id, "generic decoder", (vlc_thread_func)RunThread, (void *) p_gdec) )
{
intf_ErrMsg("gdec error: %s", strerror(ENOMEM));
intf_DbgMsg("failed");
free( p_gdec );
return( NULL );
}
/* If status is NULL, wait until the thread is created */
if( pi_status == NULL )
{
do
{
msleep( THREAD_SLEEP );
}while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
if( i_status != THREAD_READY )
{
intf_DbgMsg("failed");
return( NULL );
}
}
intf_DbgMsg("succeeded -> %p", p_gdec);
return( p_gdec );
}
/*****************************************************************************
* gdec_DestroyThread: destroy a generic decoder thread
*****************************************************************************
* Destroy a terminated thread. This function will return 0 if the thread could
* be destroyed, and non 0 else. The last case probably means that the thread
* was still active, and another try may succeed.
*****************************************************************************/
void gdec_DestroyThread( gdec_thread_t *p_gdec, int *pi_status )
{
int i_status; /* thread status */
/* Set status */
p_gdec->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_gdec->pi_status = THREAD_DESTROY;
/* Request thread destruction */
p_gdec->b_die = 1;
/* Make sure the decoder thread leaves the GetByte() function */
vlc_mutex_lock( &(p_gdec->fifo.data_lock) );
vlc_cond_signal( &(p_gdec->fifo.data_wait) );
vlc_mutex_unlock( &(p_gdec->fifo.data_lock) );
/* If status is NULL, wait until thread has been destroyed */
if( pi_status )
{
do
{
msleep( THREAD_SLEEP );
}while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
}
intf_DbgMsg("%p -> succeeded", p_gdec);
}
/* following functions are local */
/*****************************************************************************
* CheckConfiguration: check gdec_CreateThread() configuration
*****************************************************************************
* Set default parameters where required. In DEBUG mode, check if configuration
* is valid.
*****************************************************************************/
static int CheckConfiguration( gdec_cfg_t *p_cfg )
{
#ifdef DEBUG
/* Actions (required) */
if( !(p_cfg->i_properties & GDEC_CFG_ACTIONS) )
{
return( 1 );
}
#endif
return( 0 );
}
/*****************************************************************************
* InitThread: initialize gdec thread
*****************************************************************************
* This function is called from RunThread and performs the second step of the
* initialization. It returns 0 on success. Note that the thread's flag are not
* modified inside this function.
*****************************************************************************/
static int InitThread( gdec_thread_t *p_gdec )
{
/* XXX?? */
/* Update status */
*p_gdec->pi_status = THREAD_START;
/* Initialize other properties */
#ifdef STATS
p_gdec->c_loops = 0;
p_gdec->c_idle_loops = 0;
p_gdec->c_pes = 0;
#endif
/* Mark thread as running and return */
*p_gdec->pi_status = THREAD_READY;
intf_DbgMsg("%p -> succeeded", p_gdec);
return(0);
}
/*****************************************************************************
* RunThread: generic decoder thread
*****************************************************************************
* Generic decoder thread. This function does only returns when the thread is
* terminated.
*****************************************************************************/
static void RunThread( gdec_thread_t *p_gdec )
{
pes_packet_t * p_pes; /* current packet */
int i_stream_id; /* PES stream id */
/*
* Initialize thread and free configuration
*/
p_gdec->b_error = InitThread( p_gdec );
if( p_gdec->b_error )
{
free( p_gdec ); /* destroy descriptor */
return;
}
/*
* Main loop - it is not executed if an error occured during
* initialization
*/
while( (!p_gdec->b_die) && (!p_gdec->b_error) )
{
/* FIXME: locks rajouter ?? - vrifier les macros (transformer en inline ?) */
/* on idle loop, increment c_idle_loops */
while( !DECODER_FIFO_ISEMPTY( p_gdec->fifo ) )
{
p_pes = DECODER_FIFO_START( p_gdec->fifo );
DECODER_FIFO_INCSTART( p_gdec->fifo );
/* Extract stream id from packet if required - stream id is used
* by GDEC_IDENTIFY, GDEC_SAVE_DEMUX and GDEC_PRINT */
if( p_gdec->i_actions & (GDEC_IDENTIFY | GDEC_SAVE_DEMUX | GDEC_PRINT) )
{
i_stream_id = p_pes->p_pes_header[3];
}
/* PES identification */
if( p_gdec->i_actions & GDEC_IDENTIFY )
{
IdentifyPES( p_gdec, p_pes, i_stream_id );
}
/* PES multiplexed stream saving */
if( p_gdec->i_actions & GDEC_SAVE )
{
/* XXX?? */
}
/* PES demultiplexed stream saving */
if( p_gdec->i_actions & GDEC_SAVE_DEMUX )
{
/* XXX?? */
}
/* PES information printing */
if( p_gdec->i_actions & GDEC_PRINT )
{
PrintPES( p_pes, i_stream_id );
}
/* Trash PES packet (give it back to fifo) */
input_NetlistFreePES( p_gdec->p_input, p_pes );
#ifdef STATS
p_gdec->c_pes++;
#endif
}
#ifdef STATS
p_gdec->c_loops++;
#endif
}
/*
* Error loop
*/
if( p_gdec->b_error )
{
ErrorThread( p_gdec );
}
/* End of thread */
EndThread( p_gdec );
}
/*****************************************************************************
* ErrorThread: RunThread() error loop
*****************************************************************************
* This function is called when an error occured during thread main's loop. The
* thread can still receive feed, but must be ready to terminate as soon as
* possible.
*****************************************************************************/
static void ErrorThread( gdec_thread_t *p_gdec )
{
pes_packet_t * p_pes; /* pes packet */
/* Wait until a `die' order */
while( !p_gdec->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY( p_gdec->fifo ) )
{
p_pes = DECODER_FIFO_START( p_gdec->fifo );
DECODER_FIFO_INCSTART( p_gdec->fifo );
input_NetlistFreePES( p_gdec->p_input, p_pes );
}
/* Sleep a while */
msleep( GDEC_IDLE_SLEEP );
}
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( gdec_thread_t *p_gdec )
{
int * pi_status; /* thread status */
/* Store status */
pi_status = p_gdec->pi_status;
*pi_status = THREAD_END;
#ifdef DEBUG
/* Check for remaining PES packets */
/* XXX?? */
#endif
/* Destroy thread structures allocated by InitThread */
free( p_gdec ); /* destroy descriptor */
*pi_status = THREAD_OVER;
intf_DbgMsg("%p", p_gdec);
}
/*****************************************************************************
* IdentifyPES: identify a PES packet
*****************************************************************************
* Update ES tables in the input thread according to the stream_id value. See
* ISO 13818-1, table 2-18.
*****************************************************************************/
static void IdentifyPES( gdec_thread_t *p_gdec, pes_packet_t *p_pes, int i_stream_id )
{
int i_id; /* stream id in es table */
int i_type; /* stream type according ISO/IEC 13818-1 table 2-29 */
/* Search where the elementary stream id does come from */
switch( p_gdec->p_input->i_method )
{
case INPUT_METHOD_TS_FILE: /* TS methods: id is TS PID */
case INPUT_METHOD_TS_UCAST:
case INPUT_METHOD_TS_BCAST:
case INPUT_METHOD_TS_VLAN_BCAST:
/* XXX?? since PID is extracted by demux, it could be useful to store it
* in a readable place, i.e. the TS packet descriptor, rather than to
* re-extract it now */
i_id = U16_AT(&p_pes->p_first_ts->buffer[1]) & 0x1fff;
break;
#ifdef DEBUG
default: /* unknown id origin */
intf_DbgMsg("unable to identify PES using input method %d",
p_gdec->p_input->i_method );
break;
#endif
}
/* Try to identify PES stream_id - see ISO 13818-1 table 2-18 */
if( i_stream_id == 0xbd )
{
/* Dolby AC-3 stream - might be specific to DVD PS streams */
i_type = MPEG2_AUDIO_ES;
intf_DbgMsg("PES %p identified as AUDIO AC3", p_pes);
}
else if( (i_stream_id & 0xe0) == 0xc0 )
{
/* ISO/IEC 13818-3 or ISO/IEC 11172-3 audio stream - since there is no
* way to make the difference between the two possibilities, and since
* an ISO/IEC 13818-3 is capable of decoding an ISO/IEC 11172-3 stream,
* the first one is used */
i_type = MPEG2_AUDIO_ES;
intf_DbgMsg("PES %p identified as AUDIO MPEG", p_pes);
}
else if( (i_stream_id & 0xf0) == 0xe0 )
{
/* ISO/IEC 13818-2 or ISO/IEC 11172-2 video stream - since there is no
* way to make the difference between the two possibilities, and since
* an ISO/IEC 13818-2 is capable of decoding an ISO/IEC 11172-2 stream,
* the first one is used */
i_type = MPEG2_VIDEO_ES;
intf_DbgMsg("PES %p identified as VIDEO", p_pes);
}
else
{
/* The stream could not be identified - just return */
intf_DbgMsg("PES %p could not be identified", p_pes);
return;
}
/* Update ES table */
/* XXX?? */
}
/*****************************************************************************
* PrintPES: print informations about a PES packet
*****************************************************************************
* This function will print information about a received PES packet. It is
* probably useful only for debugging purposes, or before demultiplexing a
* stream. It has two different formats, depending of the presence of the DEBUG
* symbol.
*****************************************************************************/
static void PrintPES( pes_packet_t *p_pes, int i_stream_id )
{
char psz_pes[128]; /* descriptor buffer */
#ifdef DEBUG
/* PES informations, long (DEBUG) format - this string is maximum 70 bytes
* long */
sprintf(psz_pes, "id 0x%x, %d bytes (%d TS): %p %c%c%c%c",
i_stream_id, p_pes->i_pes_size, p_pes->i_ts_packets,
p_pes,
p_pes->b_data_loss ? 'l' : '-', p_pes->b_data_alignment ? 'a' : '-',
p_pes->b_random_access ? 'r' : '-', p_pes->b_discard_payload ? 'd' : '-' );
#else
/* PES informations, short format */
sprintf(psz_pes, "id 0x%x, %d bytes",
i_stream_id, p_pes->i_pes_size );
#endif
intf_Msg("gdec: PES %s", psz_pes );
}
/*****************************************************************************
* generic_decoder.h : generic decoder thread
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: generic_decoder.h,v 1.6 2001/03/21 13:42:34 sam Exp $
*
* Authors: Vincent Seguin <seguin@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
* (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.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************
/*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "mtime.h"
* "threads.h"
* "input.h"
* "decoder_fifo.h"
* XXX??
*****************************************************************************/
/*****************************************************************************
* gdec_cfg_t: generic decoder configuration structure
*****************************************************************************
* This structure is passed as an initializer when a generic decoder thread is
* created.
*****************************************************************************/
typedef struct gdec_cfg_s
{
u64 i_properties;
int i_actions; /* decoder actions */
char * psz_base_filename; /* base demux file name */
} gdec_cfg_t;
/* Properties flags */
#define GDEC_CFG_ACTIONS (1 << 0)
#define GDEC_CFG_FILENAME (1 << 1)
/*****************************************************************************
* gdec_thread_t: generic decoder thread descriptor
*****************************************************************************
* This type describes a generic decoder thread.
*****************************************************************************/
typedef struct gdec_thread_s
{
/* Thread properties and locks */
boolean_t b_die; /* `die' flag */
boolean_t b_error; /* `error' flag */
boolean_t b_active; /* `active' flag */
vlc_thread_t thread_id; /* id for thread functions */
/* Thread configuration */
int i_actions; /* decoder actions */
/* Input properties */
input_thread_t * p_input; /* input thread */
decoder_fifo_t fifo; /* PES input fifo */
/* XXX?? status info */
int * pi_status;
/* Files array - these files are used to extract ES streams from a
* demultiplexed stream */
/* XXX?? */
#ifdef STATS
/* Statistics */
count_t c_loops; /* number of loops */
count_t c_idle_loops; /* number of idle loops */
count_t c_pes; /* number of PES packets read */
#endif
} gdec_thread_t;
/* Decoder actions - this flags select which actions the decoder will perform
* when it receives a PES packet */
#define GDEC_IDENTIFY (1 << 0) /* update input's ES tables */
#define GDEC_SAVE (1 << 1) /* save all PES to a same file */
#define GDEC_SAVE_DEMUX (1 << 2) /* save PES to files by stream id */
#define GDEC_PRINT (1 << 3) /* print PES informations */
/*****************************************************************************
* Prototypes
*****************************************************************************/
/* Thread management functions */
gdec_thread_t * gdec_CreateThread ( gdec_cfg_t *p_cfg,
input_thread_t *p_input, int *pi_status );
void gdec_DestroyThread ( gdec_thread_t *p_gdec, int *pi_status );
/* Time management functions */
/* XXX?? */
/* Dynamic thread settings */
/* XXX?? */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment