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 @@
* dshow.cpp : DirectShow access module for vlc
*****************************************************************************
* 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>
*
......@@ -34,34 +34,6 @@
#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
*****************************************************************************/
......@@ -94,6 +66,12 @@ static char *ppsz_adev_text[] = { N_("Default"), N_("None") };
"Force the DirectShow video input to use a specific chroma format " \
"(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();
set_description( _("DirectShow input") );
add_category_hint( N_("dshow"), NULL, VLC_TRUE );
......@@ -122,9 +100,28 @@ vlc_module_begin();
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:
......@@ -1134,223 +1131,181 @@ static ssize_t ReadDV( input_thread_t * p_input, byte_t * p_buffer,
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 )
{
input_thread_t *p_input = (input_thread_t *)p_this;
demux_sys_t *p_sys;
uint8_t *p_peek;
int i_streams;
int i_es;
int i;
data_packet_t *p_pk;
/* 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)" );
return VLC_EGENERIC;
}
if( strcmp( (const char *)p_peek, ".dsh" ) ||
GetDWBE( &p_peek[4] ) <= 0 )
if( strncmp( p_peek, ".dsh", 4 ) ||
( i_es = GetDWBE( &p_peek[4] ) ) <= 0 )
{
msg_Warn( p_input, "dshow plugin discarded (not a valid stream)" );
return VLC_EGENERIC;
}
/* create one program */
vlc_mutex_lock( &p_input->stream.stream_lock );
if( input_InitStream( p_input, 0 ) == -1)
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot init stream" );
return VLC_EGENERIC;
}
if( input_AddProgram( p_input, 0, 0) == NULL )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot add program" );
return VLC_EGENERIC;
return( VLC_EGENERIC );
}
p_input->stream.i_mux_rate = 0 / 50;
vlc_mutex_unlock( &p_input->stream.stream_lock );
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
p_input->stream.i_mux_rate = 0;
p_input->pf_demux = Demux;
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( input_Peek( p_input, &p_peek, 8 + 20 * i_streams )
< 8 + 20 * i_streams )
if( stream_Peek( p_input->s, &p_peek, 8 + 20 * i_es ) < 8 + 20 * i_es )
{
msg_Err( p_input, "dshow plugin discarded (cannot peek)" );
return VLC_EGENERIC;
}
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)
p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
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 ) );
wf->wFormatTag = 0;//WAVE_FORMAT_UNKNOWN;
wf->nChannels = GetDWBE( &p_peek[8] );
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",
wf->nChannels, wf->nSamplesPerSec );
input_SelectES( p_input, p_es );
#undef wf
es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( p_peek[4], p_peek[5],
p_peek[6], p_peek[7] ) );
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;
msg_Dbg( p_input, "new audio es %d channels %dHz",
fmt.audio.i_channels, fmt.audio.i_rate );
TAB_APPEND( p_sys->i_es, p_sys->es,
es_out_Add( p_input->p_es_out, &fmt ) );
}
else if( !strncmp( (const char *)p_peek, "vids", 4 ) )
else if( !strncmp( p_peek, "vids", 4 ) )
{
#define bih ((BITMAPINFOHEADER*)p_es->p_bitmapinfoheader)
p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
i + 1, VIDEO_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_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;
es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( p_peek[4], p_peek[5],
p_peek[6], p_peek[7] ) );
fmt.video.i_width = GetDWBE( &p_peek[8] );
fmt.video.i_height = GetDWBE( &p_peek[12] );
msg_Dbg( p_input, "added new video es %4.4s %dx%d",
(char*)&p_es->i_fourcc, bih->biWidth, bih->biHeight );
input_SelectES( p_input, p_es );
#undef bih
(char*)&fmt.i_codec,
fmt.video.i_width, fmt.video.i_height );
TAB_APPEND( p_sys->i_es, p_sys->es,
es_out_Add( p_input->p_es_out, &fmt ) );
}
p_peek += 20;
}
p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* Skip header */
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;
}
/****************************************************************************
* DemuxClose:
****************************************************************************/
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 )
{
es_descriptor_t *p_es;
pes_packet_t *p_pes;
demux_sys_t *p_sys = p_input->p_demux_data;
block_t *p_block;
int i_stream;
int i_es;
int i_size;
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 ?)" );
return 0;
}
i_stream = GetDWBE( &p_peek[0] );
i_size = GetDWBE( &p_peek[4] );
i_pcr = GetQWBE( &p_peek[8] );
p_es = p_input->stream.p_selected_program->pp_es[i_stream];
if( !p_es )
i_es = GetDWBE( &p_peek[0] );
if( i_es < 0 || i_es >= p_sys->i_es )
{
msg_Err( p_input, "cannot find ES" );
return -1;
}
p_pes = input_NewPES( p_input->p_method_data );
if( p_pes == NULL )
{
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;
i_size = GetDWBE( &p_peek[4] );
i_pts = GetQWBE( &p_peek[8] );
if( (i_read = input_SplitBuffer( p_input, &p_data, i_size ) ) <= 0 )
{
input_DeletePES( p_input->p_method_data, p_pes );
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;
if( ( p_block = stream_Block( p_input->s, 16 + i_size ) ) == NULL )
{
msg_Warn( p_input, "cannot read data" );
return 0;
}
p_pes->p_first->p_payload_start += 16;
p_pes->i_pes_size -= 16;
p_block->p_buffer += 16;
p_block->i_buffer -= 16;
if( p_es && p_es->p_dec )
{
/* Call the pace control. */
input_ClockManageRef( p_input, p_input->stream.p_selected_program,
i_pcr );
/* Call the pace control. */
input_ClockManageRef( p_input, p_input->stream.p_selected_program,
i_pts );
p_pes->i_pts = p_pes->i_dts = i_pcr <= 0 ? 0 :
input_ClockGetTS( p_input, p_input->stream.p_selected_program,
i_pcr );
p_block->i_dts =
p_block->i_pts = i_pcr <= 0 ? 0 :
input_ClockGetTS( p_input, p_input->stream.p_selected_program, i_pts );
input_DecodePES( p_es->p_dec, p_pes );
}
else
{
input_DeletePES( p_input->p_method_data, p_pes );
}
es_out_Send( p_input->p_es_out, p_sys->es[i_es], p_block );
return 1;
}
/*****************************************************************************
* 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