[vlc-devel] [PATCH] Handling prefered language in AsfSelectStream Better, bitrate sort and select algo Tested with asf containing 3, Videos and 24 Lang...
Rémi Denis-Courmont
remi at remlab.net
Tue Jul 16 18:20:02 CEST 2013
Please consider posting inline. Reviewing attachments is a PITA in my opinion.
>From d2c60889af4c05bab7ced9ad60d17575a560b0f2 Mon Sep 17 00:00:00 2001
From: Alain Degreffe <eczema at ecze.com>
Date: Tue, 16 Jul 2013 16:47:38 +0200
Subject: [PATCH] Handling prefered language in AsfSelectStream Better,
bitrate sort and select algo Tested with asf containing 3,
Videos and 24 Lang..
First line is a 72-characters summary. Add more paragraphs and wrap if you
need to.
---
modules/access/mms/asf.c | 233
++++++++++++++++++++++++++++++++------------
modules/access/mms/asf.h | 18 +++-
modules/access/mms/mms.c | 1 +
modules/access/mms/mmsh.c | 12 ++-
modules/access/mms/mmstu.c | 6 +-
5 files changed, 203 insertions(+), 67 deletions(-)
diff --git a/modules/access/mms/asf.c b/modules/access/mms/asf.c
index d353bfd..3005315 100644
--- a/modules/access/mms/asf.c
+++ b/modules/access/mms/asf.c
@@ -46,6 +46,8 @@ void asf_HeaderParse ( asf_header_t *hdr,
var_buffer_t buffer;
guid_t guid;
uint64_t i_size;
+ uint16_t stream_number;
+ uint16_t lang_ID;
hdr->i_file_size = 0;
hdr->i_data_packets_count = 0;
@@ -55,6 +57,7 @@ void asf_HeaderParse ( asf_header_t *hdr,
hdr->stream[i].i_cat = ASF_CODEC_TYPE_UNKNOWN;
hdr->stream[i].i_selected = 0;
hdr->stream[i].i_bitrate = -1;
+ hdr->stream[i].i_lang_id = -1;
}
var_buffer_initread( &buffer, p_header, i_header );
@@ -93,8 +96,15 @@ void asf_HeaderParse ( asf_header_t *hdr,
int16_t i_count1, i_count2;
int i_subsize;
- var_buffer_getmemory( &buffer, NULL, 84 - 24 );
+ var_buffer_getmemory( &buffer, NULL, 72 - 24 );
+ stream_number = var_buffer_get16( &buffer );
+ lang_ID = var_buffer_get16( &buffer );
+
+ hdr->stream[stream_number].i_lang_id = lang_ID;
+
+ var_buffer_getmemory( &buffer, NULL, 8 );
+
i_count1 = var_buffer_get16( &buffer );
i_count2 = var_buffer_get16( &buffer );
@@ -167,6 +177,48 @@ void asf_HeaderParse ( asf_header_t *hdr,
}
var_buffer_getmemory( &buffer, NULL, i_size - 24 );
}
+ else if( guidcmp( &guid, &asf_object_language_list ) )
+ {
+ int i_count;
+ uint64_t i_langid_len;
+ int i_lang_str_len;
+ uint8_t *pi_ws_lang_str;
+ char *psz_lang_str;
+ int i_current_id;
+
+ i_count = var_buffer_get16( &buffer );
+
+ for( i_current_id = 0 ; i_current_id < i_count ; i_current_id++ )
+ {
+ i_langid_len = var_buffer_get8( &buffer );
+ i_lang_str_len = i_langid_len / 2;
+
+ psz_lang_str = malloc( i_lang_str_len );
+ pi_ws_lang_str = malloc( i_langid_len );
+
+ if( !psz_lang_str || !pi_ws_lang_str )
+ {
+ /* Malloc problem - Zap the remaining bytes of object */
+ var_buffer_getmemory( &buffer, NULL, i_langid_len );
+ free( psz_lang_str );
+ free( pi_ws_lang_str );
+ continue ;
+ }
+
+ var_buffer_getmemory( &buffer, pi_ws_lang_str , i_langid_len );
+ asf_wstr2str( psz_lang_str, pi_ws_lang_str,i_langid_len );
+
+ hdr->ppsz_tablang[i_current_id] = malloc( i_lang_str_len );
+ if( hdr->ppsz_tablang[i_current_id] )
+ {
+ memcpy( hdr->ppsz_tablang[i_current_id],
+ psz_lang_str, i_lang_str_len );
+ }
strndup() ?
And I cannot see where the table content is free()d.
+ free( psz_lang_str );
+ free( pi_ws_lang_str );
+ }
+ }
+
else
{
// skip unknown guid
@@ -178,21 +230,44 @@ void asf_HeaderParse ( asf_header_t *hdr,
}
}
-void asf_StreamSelect ( asf_header_t *hdr,
- int i_bitrate_max,
- bool b_all, bool b_audio, bool b_video )
+void asf_ClearCandidate ( asf_candidate_t *cell )
+{
+ asf_candidate_t * tmp;
+ while( cell->next )
+ {
+ tmp = cell ;
+ cell = tmp->next;
+ free(tmp);
+ }
+ free(cell);
+}
+
+asf_candidate_t * asf_AddCandidate( asf_candidate_t *work_Candidate,
+ int stream_candidate_id )
+{
+ work_Candidate->value = stream_candidate_id;
+ work_Candidate->next = malloc( sizeof( asf_candidate_t ) );
+ if( !work_Candidate->next ) return work_Candidate;
+ work_Candidate = work_Candidate->next;
+ work_Candidate->next = NULL;
+ return work_Candidate;
+}
+
+void asf_StreamSelect ( asf_header_t *hdr,
+ int i_bitrate_max,
+ bool b_all,
+ bool b_audio,
+ bool b_video,
+ const char * psz_lang )
{
/* XXX FIXME use mututal eclusion information */
unsigned i;
int i_audio, i_video;
- int i_bitrate_total;
+ int i_bitrate_var, i_bitrate_total;
#if 0
char *psz_stream;
#endif
- i_audio = 0;
- i_video = 0;
- i_bitrate_total = 0;
if( b_all )
{
/* select all valid stream */
@@ -214,78 +289,110 @@ void asf_StreamSelect ( asf_header_t *hdr,
}
}
- /* big test:
- * select a stream if
- * - no audio nor video stream
- * - or:
- * - if i_bitrate_max not set keep the highest bitrate
- * - if i_bitrate_max is set, keep stream that make we used best
- * quality regarding i_bitrate_max
- *
- * XXX: little buggy:
- * - it doesn't use mutual exclusion info..
- * - when selecting a better stream we could select
- * something that make i_bitrate_total> i_bitrate_max
- */
- for( i = 1; i < 128; i++ )
+ i_audio = -1;
+ i_video = -1;
+ i_bitrate_total = 0;
+ i_bitrate_var = 0;
+
+ asf_candidate_t * head_Candidatefavlang, * courant_Candidatefavlang;
+ asf_candidate_t * head_Candidateotherlang, *
courant_Candidateotherlang;
+ asf_candidate_t * head_CandidateVideo, * courant_CandidateVideo;
+ asf_candidate_t * work_Candidate;
+
+ head_Candidatefavlang = malloc( sizeof( asf_candidate_t ) );
+ head_Candidateotherlang = malloc( sizeof( asf_candidate_t ) );
+ head_CandidateVideo = malloc( sizeof( asf_candidate_t ) );
+
+ if( !head_Candidatefavlang || !head_Candidatefavlang ||
+ !head_Candidatefavlang )
+ {
+ free( head_Candidatefavlang );
+ free( head_Candidatefavlang );
+ free( head_Candidatefavlang );
+ return;
+ }
+
+ head_Candidatefavlang->next = NULL;
+ courant_Candidatefavlang = head_Candidatefavlang;
+
+ head_Candidateotherlang->next = NULL;
+ courant_Candidateotherlang = head_Candidateotherlang;
+
+ head_CandidateVideo->next = NULL;
+ courant_CandidateVideo = head_CandidateVideo;
+
+ for( i = 1 ; i < 128 ; i++ )
{
if( hdr->stream[i].i_cat == ASF_CODEC_TYPE_UNKNOWN )
{
continue;
}
- else if( hdr->stream[i].i_cat == ASF_CODEC_TYPE_AUDIO && b_audio &&
- ( i_audio <= 0 ||
- ( ( ( hdr->stream[i].i_bitrate > hdr-
>stream[i_audio].i_bitrate &&
- ( i_bitrate_total + hdr->stream[i].i_bitrate - hdr-
>stream[i_audio].i_bitrate
- < i_bitrate_max ||
!i_bitrate_max) ) ||
- ( hdr->stream[i].i_bitrate < hdr-
>stream[i_audio].i_bitrate &&
- i_bitrate_max != 0 && i_bitrate_total >
i_bitrate_max )
- ) ) ) )
+
+ /* audio */
+ if( hdr->stream[i].i_cat == ASF_CODEC_TYPE_AUDIO && b_audio &&
+ ( hdr->stream[i].i_bitrate < i_bitrate_max || !i_bitrate_max )
)
{
- /* unselect old stream */
- if( i_audio > 0 )
+ if( psz_lang != NULL &&
+ strcmp( hdr->ppsz_tablang[hdr->stream[i].i_lang_id], psz_lang
) == 0 )
{
- hdr->stream[i_audio].i_selected = 0;
- if( hdr->stream[i_audio].i_bitrate> 0 )
- {
- i_bitrate_total -= hdr->stream[i_audio].i_bitrate;
- }
+ courant_Candidatefavlang =
asf_AddCandidate(courant_Candidatefavlang, i);
}
-
- hdr->stream[i].i_selected = 1;
- if( hdr->stream[i].i_bitrate> 0 )
+ else
{
- i_bitrate_total += hdr->stream[i].i_bitrate;
+ courant_Candidateotherlang =
asf_AddCandidate(courant_Candidateotherlang, i);
}
- i_audio = i;
}
+ /* video */
else if( hdr->stream[i].i_cat == ASF_CODEC_TYPE_VIDEO && b_video &&
- ( i_video <= 0 ||
- (
- ( ( hdr->stream[i].i_bitrate > hdr-
>stream[i_video].i_bitrate &&
- ( i_bitrate_total + hdr->stream[i].i_bitrate -
hdr->stream[i_video].i_bitrate
- < i_bitrate_max ||
!i_bitrate_max) ) ||
- ( hdr->stream[i].i_bitrate < hdr-
>stream[i_video].i_bitrate &&
- i_bitrate_max != 0 && i_bitrate_total >
i_bitrate_max )
- ) ) ) )
+ ( hdr->stream[i].i_bitrate < i_bitrate_max || !i_bitrate_max
) )
{
- /* unselect old stream */
- if( i_video > 0 )
- {
- hdr->stream[i_video].i_selected = 0;
- if( hdr->stream[i_video].i_bitrate> 0 )
- {
- i_bitrate_total -= hdr->stream[i_video].i_bitrate;
- }
- }
+ courant_CandidateVideo = asf_AddCandidate(courant_CandidateVideo,
i);
+ }
+ }
+
+ if( head_Candidatefavlang->next )
+ {
+ work_Candidate = head_Candidatefavlang;
+ }
+ else
+ {
+ work_Candidate = head_Candidateotherlang;
+ }
+
+ courant_CandidateVideo = head_CandidateVideo;
- hdr->stream[i].i_selected = 1;
- if( hdr->stream[i].i_bitrate> 0 )
+ while( work_Candidate->next )
+ {
+ while( courant_CandidateVideo->next )
+ {
+ i_bitrate_var = hdr->stream[work_Candidate->value].i_bitrate
+ + hdr->stream[courant_CandidateVideo-
>value].i_bitrate;
+ if( i_bitrate_var > i_bitrate_total &&
+ ( !i_bitrate_max || i_bitrate_var < i_bitrate_max ) )
{
- i_bitrate_total += hdr->stream[i].i_bitrate;
+ i_audio = work_Candidate->value;
+ i_video = courant_CandidateVideo->value;
+ i_bitrate_total = i_bitrate_var;
}
- i_video = i;
+ courant_CandidateVideo = courant_CandidateVideo->next;
}
+ i_bitrate_var = hdr->stream[work_Candidate->value].i_bitrate;
+ if( i_bitrate_var > i_bitrate_total &&
+ ( !i_bitrate_max || i_bitrate_var < i_bitrate_max ) )
+ {
+ i_audio = work_Candidate->value;
+ i_bitrate_total = i_bitrate_var;
+ }
+ work_Candidate = work_Candidate->next;
}
+
+ /* select stream */
+ if( i_audio != -1 ) hdr->stream[i_audio].i_selected = 1;
+ if( i_video != -1 ) hdr->stream[i_video].i_selected = 1;
+
+ /* clear structures */
+ asf_ClearCandidate( head_Candidatefavlang );
+ asf_ClearCandidate( head_Candidateotherlang );
+ asf_ClearCandidate( head_CandidateVideo );
}
diff --git a/modules/access/mms/asf.h b/modules/access/mms/asf.h
index f15b90d..a7d0725 100644
--- a/modules/access/mms/asf.h
+++ b/modules/access/mms/asf.h
@@ -42,6 +42,7 @@ typedef struct
int i_cat; /* ASF_CODEC_TYPE_VIDEO, ASF_CODEC_TYPE_AUDIO, */
int i_bitrate; /* -1 if unknown */
int i_selected;
+ int i_lang_id;
} asf_stream_t;
typedef struct
@@ -49,16 +50,31 @@ typedef struct
int64_t i_file_size;
int64_t i_data_packets_count;
int32_t i_min_data_packet_size;
+ char * ppsz_tablang[128];
asf_stream_t stream[128];
} asf_header_t;
+typedef struct asf_candidate_t
+{
+ int value ;
+ struct asf_candidate_t *next;
+} asf_candidate_t;
void GenerateGuid ( guid_t * );
+asf_candidate_t * asf_AddCandidate( asf_candidate_t *, int );
+void asf_ClearCandidate ( asf_candidate_t *);
void asf_HeaderParse ( asf_header_t *, uint8_t *, int );
void asf_StreamSelect ( asf_header_t *,
int i_bitrate_max, bool b_all, bool b_audio,
- bool b_video );
+ bool b_video , const char * psz_preflang );
+static inline void asf_wstr2str( char * dst, uint8_t * src , int inlen )
+{
+ for( int i = 0 ; i < inlen ; i += 2 )
+ {
+ dst[i/2] = GetWLE( &src[i] );
+ }
+};
#endif
diff --git a/modules/access/mms/mms.c b/modules/access/mms/mms.c
index 5633c10..591315e 100644
--- a/modules/access/mms/mms.c
+++ b/modules/access/mms/mms.c
@@ -77,6 +77,7 @@ vlc_module_begin ()
add_bool( "mms-all", false, ALL_TEXT, ALL_LONGTEXT, true )
add_integer( "mms-maxbitrate", 0, BITRATE_TEXT, BITRATE_LONGTEXT ,
false )
+ change_safe()
add_string( "mmsh-proxy", NULL, PROXY_TEXT, PROXY_LONGTEXT,
false )
diff --git a/modules/access/mms/mmsh.c b/modules/access/mms/mmsh.c
index 2a36670..5a0743f 100644
--- a/modules/access/mms/mmsh.c
+++ b/modules/access/mms/mmsh.c
@@ -440,6 +440,7 @@ static int Reset( access_t *p_access )
access_sys_t *p_sys = p_access->p_sys;
asf_header_t old_asfh = p_sys->asfh;
int i;
+ char * psz_preflang;
msg_Dbg( p_access, "Reset the stream" );
p_sys->i_start = p_access->info.i_pos;
@@ -461,11 +462,14 @@ static int Reset( access_t *p_access )
p_sys->asfh.i_data_packets_count,
p_sys->asfh.i_min_data_packet_size );
+ psz_preflang = var_InheritString( p_access->p_parent, "audio-language" );
Why are you accessing p_parent here??
Furthermore, why do you use the default audio track language here?
If you want to hint the server about the user locale, then the language
identifier is _("C") instead. On the other hand, if you want to filter tracks to
save bandwidth, then you should add a control query from the ASF demux to the
MMS access (like betweem MPEG-TS demux and DTV access).
If you force filtering at the access level, next month users will whine that
they cannot override the track selection from the UI anymore...
asf_StreamSelect( &p_sys->asfh,
var_InheritInteger( p_access, "mms-maxbitrate" ),
var_InheritBool( p_access, "mms-all" ),
var_InheritBool( p_access, "audio" ),
- var_InheritBool( p_access, "video" ) );
+ var_InheritBool( p_access, "video" ),
+ psz_preflang );
+ free (psz_preflang);
/* Check we have comptible asfh */
for( i = 1; i < 128; i++ )
@@ -552,6 +556,7 @@ static int Describe( access_t *p_access, char
**ppsz_location )
bool b_keepalive = false;
char *psz;
int i_code;
+ char *psz_preflang;
/* Reinit context */
p_sys->b_broadcast = true;
@@ -714,11 +719,14 @@ static int Describe( access_t *p_access, char
**ppsz_location )
if( p_sys->asfh.i_min_data_packet_size <= 0 )
goto error;
+ psz_preflang = var_InheritString( p_access->p_parent, "audio-language" );
asf_StreamSelect( &p_sys->asfh,
var_InheritInteger( p_access, "mms-maxbitrate" ),
var_InheritBool( p_access, "mms-all" ),
var_InheritBool( p_access, "audio" ),
- var_InheritBool( p_access, "video" ) );
+ var_InheritBool( p_access, "video" ),
+ psz_preflang );
+ free( psz_preflang );
return VLC_SUCCESS;
error:
diff --git a/modules/access/mms/mmstu.c b/modules/access/mms/mmstu.c
index 932c59f..dbb3fe5 100644
--- a/modules/access/mms/mmstu.c
+++ b/modules/access/mms/mmstu.c
@@ -467,6 +467,7 @@ static int MMSOpen( access_t *p_access, vlc_url_t *p_url,
int i_proto )
int i_streams;
int i_first;
char *mediapath;
+ char *psz_preflang;
/* *** Open a TCP connection with server *** */
@@ -788,11 +789,14 @@ static int MMSOpen( access_t *p_access, vlc_url_t
*p_url, int i_proto )
* and bitrate mutual exclusion(optional) */
asf_HeaderParse ( &p_sys->asfh,
p_sys->p_header, p_sys->i_header );
+ psz_preflang = var_InheritString( p_access->p_parent, "audio-language" );
asf_StreamSelect( &p_sys->asfh,
var_InheritInteger( p_access, "mms-maxbitrate" ),
var_InheritBool( p_access, "mms-all" ),
var_InheritBool( p_access, "audio" ),
- var_InheritBool( p_access, "video" ) );
+ var_InheritBool( p_access, "video" ),
+ psz_preflang );
+ free( psz_preflang );
Same remark as above.
/* *** now select stream we want to receive *** */
/* TODO take care of stream bitrate TODO */
--
1.7.9.5
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list