Commit 29920e21 authored by Laurent Aimar's avatar Laurent Aimar

* dshow: ported to es_out_* and stream_*. Not tested (sorry).

parent df0c60d6
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dshow.cpp : DirectShow access module for vlc * dshow.cpp : DirectShow access module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: dshow.cpp,v 1.14 2003/11/24 00:39:01 fenrir Exp $ * $Id: dshow.cpp,v 1.15 2003/11/24 19:30:54 fenrir Exp $
* *
* Author: Gildas Bazin <gbazin@netcourrier.com> * Author: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -34,34 +34,6 @@ ...@@ -34,34 +34,6 @@
#include "filter.h" #include "filter.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int AccessOpen ( vlc_object_t * );
static void AccessClose ( vlc_object_t * );
static ssize_t Read ( input_thread_t *, byte_t *, size_t );
static ssize_t ReadDV ( input_thread_t *, byte_t *, size_t );
static int DemuxOpen ( vlc_object_t * );
static void DemuxClose ( vlc_object_t * );
static int Demux ( input_thread_t * );
static int OpenDevice( input_thread_t *, string, vlc_bool_t );
static IBaseFilter *FindCaptureDevice( vlc_object_t *, string *,
list<string> *, vlc_bool_t );
static AM_MEDIA_TYPE EnumDeviceCaps( vlc_object_t *, IBaseFilter *,
int, int, int, int, int, int );
static bool ConnectFilters( IFilterGraph *, IBaseFilter *, IPin * );
static int FindDevicesCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
#if 0
/* Debug only, use this to find out GUIDs */
unsigned char p_st[];
UuidToString( (IID *)&IID_IAMBufferNegotiation, &p_st );
msg_Err( p_input, "BufferNegotiation: %s" , p_st );
#endif
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -94,6 +66,12 @@ static char *ppsz_adev_text[] = { N_("Default"), N_("None") }; ...@@ -94,6 +66,12 @@ static char *ppsz_adev_text[] = { N_("Default"), N_("None") };
"Force the DirectShow video input to use a specific chroma format " \ "Force the DirectShow video input to use a specific chroma format " \
"(eg. I420 (default), RV24, etc...)") "(eg. I420 (default), RV24, etc...)")
static int AccessOpen ( vlc_object_t * );
static void AccessClose( vlc_object_t * );
static int DemuxOpen ( vlc_object_t * );
static void DemuxClose ( vlc_object_t * );
vlc_module_begin(); vlc_module_begin();
set_description( _("DirectShow input") ); set_description( _("DirectShow input") );
add_category_hint( N_("dshow"), NULL, VLC_TRUE ); add_category_hint( N_("dshow"), NULL, VLC_TRUE );
...@@ -122,9 +100,28 @@ vlc_module_begin(); ...@@ -122,9 +100,28 @@ vlc_module_begin();
vlc_module_end(); vlc_module_end();
/****************************************************************************
* I. Access Part /*****************************************************************************
****************************************************************************/ * Access: local prototypes
*****************************************************************************/
static ssize_t Read ( input_thread_t *, byte_t *, size_t );
static ssize_t ReadDV ( input_thread_t *, byte_t *, size_t );
static int OpenDevice( input_thread_t *, string, vlc_bool_t );
static IBaseFilter *FindCaptureDevice( vlc_object_t *, string *,
list<string> *, vlc_bool_t );
static AM_MEDIA_TYPE EnumDeviceCaps( vlc_object_t *, IBaseFilter *,
int, int, int, int, int, int );
static bool ConnectFilters( IFilterGraph *, IBaseFilter *, IPin * );
static int FindDevicesCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
#if 0
/* Debug only, use this to find out GUIDs */
unsigned char p_st[];
UuidToString( (IID *)&IID_IAMBufferNegotiation, &p_st );
msg_Err( p_input, "BufferNegotiation: %s" , p_st );
#endif
/* /*
* header: * header:
...@@ -1134,223 +1131,181 @@ static ssize_t ReadDV( input_thread_t * p_input, byte_t * p_buffer, ...@@ -1134,223 +1131,181 @@ static ssize_t ReadDV( input_thread_t * p_input, byte_t * p_buffer,
return 0; /* never reached */ return 0; /* never reached */
} }
/*****************************************************************************
* Demux: local prototypes
*****************************************************************************/
struct demux_sys_t
{
int i_es;
es_out_id_t **es;
};
static int Demux ( input_thread_t * );
/**************************************************************************** /****************************************************************************
* I. Demux Part * DemuxOpen:
****************************************************************************/ ****************************************************************************/
static int DemuxOpen( vlc_object_t *p_this ) static int DemuxOpen( vlc_object_t *p_this )
{ {
input_thread_t *p_input = (input_thread_t *)p_this; input_thread_t *p_input = (input_thread_t *)p_this;
demux_sys_t *p_sys;
uint8_t *p_peek; uint8_t *p_peek;
int i_streams; int i_es;
int i; int i;
data_packet_t *p_pk;
/* a little test to see if it's a dshow stream */ /* a little test to see if it's a dshow stream */
if( input_Peek( p_input, &p_peek, 8 ) < 8 ) if( stream_Peek( p_input->s, &p_peek, 8 ) < 8 )
{ {
msg_Warn( p_input, "dshow plugin discarded (cannot peek)" ); msg_Warn( p_input, "dshow plugin discarded (cannot peek)" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if( strcmp( (const char *)p_peek, ".dsh" ) || if( strncmp( p_peek, ".dsh", 4 ) ||
GetDWBE( &p_peek[4] ) <= 0 ) ( i_es = GetDWBE( &p_peek[4] ) ) <= 0 )
{ {
msg_Warn( p_input, "dshow plugin discarded (not a valid stream)" ); msg_Warn( p_input, "dshow plugin discarded (not a valid stream)" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* create one program */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
if( input_InitStream( p_input, 0 ) == -1) if( input_InitStream( p_input, 0 ) == -1)
{ {
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot init stream" ); msg_Err( p_input, "cannot init stream" );
return VLC_EGENERIC; return( VLC_EGENERIC );
} }
if( input_AddProgram( p_input, 0, 0) == NULL ) p_input->stream.i_mux_rate = 0 / 50;
{
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot add program" );
return VLC_EGENERIC;
}
p_input->stream.p_selected_program = p_input->stream.pp_programs[0]; p_input->pf_demux = Demux;
p_input->stream.i_mux_rate = 0; p_input->pf_demux_control = demux_vaControlDefault;
p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
p_sys->i_es = 0;
p_sys->es = NULL;
i_streams = GetDWBE( &p_peek[4] ); if( stream_Peek( p_input->s, &p_peek, 8 + 20 * i_es ) < 8 + 20 * i_es )
if( input_Peek( p_input, &p_peek, 8 + 20 * i_streams )
< 8 + 20 * i_streams )
{ {
msg_Err( p_input, "dshow plugin discarded (cannot peek)" ); msg_Err( p_input, "dshow plugin discarded (cannot peek)" );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_peek += 8; p_peek += 8;
for( i = 0; i < i_streams; i++ ) for( i = 0; i < i_es; i++ )
{ {
es_descriptor_t *p_es; es_format_t fmt;
if( !strncmp( (const char *)p_peek, "auds", 4 ) ) if( !strncmp( p_peek, "auds", 4 ) )
{ {
#define wf ((WAVEFORMATEX*)p_es->p_waveformatex) es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( p_peek[4], p_peek[5],
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], p_peek[6], p_peek[7] ) );
i + 1, AUDIO_ES, NULL, 0 );
p_es->i_stream_id = i + 1;
p_es->i_fourcc =
VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) ); fmt.audio.i_channels = GetDWBE( &p_peek[8] );
fmt.audio.i_rate = GetDWBE( &p_peek[12] );
fmt.audio.i_bitspersample = GetDWBE( &p_peek[16] );
fmt.audio.i_blockalign = fmt.audio.i_channels *
fmt.audio.i_bitspersample / 8;
fmt.i_bitrate = fmt.audio.i_channels *
fmt.audio.i_rate *
fmt.audio.i_bitspersample;
wf->wFormatTag = 0;//WAVE_FORMAT_UNKNOWN; msg_Dbg( p_input, "new audio es %d channels %dHz",
wf->nChannels = GetDWBE( &p_peek[8] ); fmt.audio.i_channels, fmt.audio.i_rate );
wf->nSamplesPerSec = GetDWBE( &p_peek[12] );
wf->wBitsPerSample = GetDWBE( &p_peek[16] );
wf->nBlockAlign = wf->wBitsPerSample * wf->nChannels / 8;
wf->nAvgBytesPerSec = wf->nBlockAlign * wf->nSamplesPerSec;
wf->cbSize = 0;
msg_Dbg( p_input, "added new audio es %d channels %dHz", TAB_APPEND( p_sys->i_es, p_sys->es,
wf->nChannels, wf->nSamplesPerSec ); es_out_Add( p_input->p_es_out, &fmt ) );
input_SelectES( p_input, p_es );
#undef wf
} }
else if( !strncmp( (const char *)p_peek, "vids", 4 ) ) else if( !strncmp( p_peek, "vids", 4 ) )
{ {
#define bih ((BITMAPINFOHEADER*)p_es->p_bitmapinfoheader) es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( p_peek[4], p_peek[5],
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], p_peek[6], p_peek[7] ) );
i + 1, VIDEO_ES, NULL, 0 ); fmt.video.i_width = GetDWBE( &p_peek[8] );
p_es->i_stream_id = i + 1; fmt.video.i_height = GetDWBE( &p_peek[12] );
p_es->i_fourcc =
VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
p_es->p_bitmapinfoheader = malloc( sizeof( BITMAPINFOHEADER ) );
bih->biSize = sizeof( BITMAPINFOHEADER );
bih->biWidth = GetDWBE( &p_peek[8] );
bih->biHeight = GetDWBE( &p_peek[12] );
bih->biPlanes = 0;
bih->biBitCount = 0;
bih->biCompression = 0;
bih->biSizeImage= 0;
bih->biXPelsPerMeter = 0;
bih->biYPelsPerMeter = 0;
bih->biClrUsed = 0;
bih->biClrImportant = 0;
msg_Dbg( p_input, "added new video es %4.4s %dx%d", msg_Dbg( p_input, "added new video es %4.4s %dx%d",
(char*)&p_es->i_fourcc, bih->biWidth, bih->biHeight ); (char*)&fmt.i_codec,
fmt.video.i_width, fmt.video.i_height );
input_SelectES( p_input, p_es ); TAB_APPEND( p_sys->i_es, p_sys->es,
#undef bih es_out_Add( p_input->p_es_out, &fmt ) );
} }
p_peek += 20; p_peek += 20;
} }
p_input->stream.p_selected_program->b_is_ok = 1; /* Skip header */
vlc_mutex_unlock( &p_input->stream.stream_lock ); stream_Read( p_input->s, NULL, 8 + 20 * i_es );
if( input_SplitBuffer( p_input, &p_pk, 8 + i_streams * 20 ) > 0 )
{
input_DeletePacket( p_input->p_method_data, p_pk );
}
p_input->pf_demux = Demux;
p_input->pf_demux_control = demux_vaControlDefault;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/****************************************************************************
* DemuxClose:
****************************************************************************/
static void DemuxClose( vlc_object_t *p_this ) static void DemuxClose( vlc_object_t *p_this )
{ {
return; input_thread_t *p_input = (input_thread_t *)p_this;
demux_sys_t *p_sys = p_input->p_demux_data;
if( p_sys->i_es > 0 )
{
free( p_sys->es );
}
free( p_sys );
} }
/****************************************************************************
* Demux:
****************************************************************************/
static int Demux( input_thread_t *p_input ) static int Demux( input_thread_t *p_input )
{ {
es_descriptor_t *p_es; demux_sys_t *p_sys = p_input->p_demux_data;
pes_packet_t *p_pes; block_t *p_block;
int i_stream; int i_es;
int i_size; int i_size;
uint8_t *p_peek; uint8_t *p_peek;
mtime_t i_pcr; mtime_t i_pts;
if( input_Peek( p_input, &p_peek, 16 ) < 16 ) if( stream_Peek( p_input->s, &p_peek, 16 ) < 16 )
{ {
msg_Warn( p_input, "cannot peek (EOF ?)" ); msg_Warn( p_input, "cannot peek (EOF ?)" );
return 0; return 0;
} }
i_stream = GetDWBE( &p_peek[0] ); i_es = GetDWBE( &p_peek[0] );
i_size = GetDWBE( &p_peek[4] ); if( i_es < 0 || i_es >= p_sys->i_es )
i_pcr = GetQWBE( &p_peek[8] );
p_es = p_input->stream.p_selected_program->pp_es[i_stream];
if( !p_es )
{ {
msg_Err( p_input, "cannot find ES" ); msg_Err( p_input, "cannot find ES" );
return -1;
} }
p_pes = input_NewPES( p_input->p_method_data ); i_size = GetDWBE( &p_peek[4] );
if( p_pes == NULL ) i_pts = GetQWBE( &p_peek[8] );
{
msg_Warn( p_input, "cannot allocate PES" );
msleep( 1000 );
return 1;
}
i_size += 16;
while( i_size > 0 )
{
data_packet_t *p_data;
int i_read;
if( (i_read = input_SplitBuffer( p_input, &p_data, i_size ) ) <= 0 ) if( ( p_block = stream_Block( p_input->s, 16 + i_size ) ) == NULL )
{ {
input_DeletePES( p_input->p_method_data, p_pes ); msg_Warn( p_input, "cannot read data" );
return 0; return 0;
} }
if( !p_pes->p_first )
{
p_pes->p_first = p_data;
p_pes->i_nb_data = 1;
p_pes->i_pes_size = i_read;
}
else
{
p_pes->p_last->p_next = p_data;
p_pes->i_nb_data++;
p_pes->i_pes_size += i_read;
}
p_pes->p_last = p_data;
i_size -= i_read;
}
p_pes->p_first->p_payload_start += 16; p_block->p_buffer += 16;
p_pes->i_pes_size -= 16; p_block->i_buffer -= 16;
if( p_es && p_es->p_dec )
{
/* Call the pace control. */ /* Call the pace control. */
input_ClockManageRef( p_input, p_input->stream.p_selected_program, input_ClockManageRef( p_input, p_input->stream.p_selected_program,
i_pcr ); i_pts );
p_pes->i_pts = p_pes->i_dts = i_pcr <= 0 ? 0 : p_block->i_dts =
input_ClockGetTS( p_input, p_input->stream.p_selected_program, p_block->i_pts = i_pcr <= 0 ? 0 :
i_pcr ); input_ClockGetTS( p_input, p_input->stream.p_selected_program, i_pts );
input_DecodePES( p_es->p_dec, p_pes ); es_out_Send( p_input->p_es_out, p_sys->es[i_es], p_block );
}
else
{
input_DeletePES( p_input->p_method_data, p_pes );
}
return 1; return 1;
} }
/***************************************************************************** /*****************************************************************************
* config variable callback * config variable callback
*****************************************************************************/ *****************************************************************************/
......
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