[vlc-devel] [PATCH] Handling prefered language in AsfSelectStream Better, bitrate sort and select algo Tested with asf containing 3, Videos and 24 Lang...
Alain Degreffe
eczema at ecze.com
Wed Jul 10 13:42:00 CEST 2013
Patch wrote by Alain Degreffe and Elodie Thomann
Regards,
---
modules/access/mms/asf.c | 212
++++++++++++++++++++++++++++++--------------
modules/access/mms/asf.h | 12 ++-
modules/access/mms/mmsh.c | 6 +-
modules/access/mms/mmstu.c | 3 +-
4 files changed, 164 insertions(+), 69 deletions(-)
diff --git a/modules/access/mms/asf.c b/modules/access/mms/asf.c
index d353bfd..916f994 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,14 @@ 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 );
@@ -151,7 +160,7 @@ void asf_HeaderParse ( asf_header_t *hdr,
hdr->stream[i_stream_id].i_cat = ASF_CODEC_TYPE_UNKNOWN;
}
}
- else if ( guidcmp( &guid, &asf_object_stream_bitrate_properties ) )
+ else if( guidcmp( &guid, &asf_object_stream_bitrate_properties ) )
{
int i_count;
uint8_t i_stream_id;
@@ -167,6 +176,40 @@ 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;
+ char * s_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 );
+ s_lang_str = malloc( i_langid_len/2 );
+ if( !s_lang_str )
+ {
+ /* Malloc problem - Zap the remaining bytes of
object */
+ var_buffer_getmemory( &buffer, NULL, i_langid_len );
+ continue;
+ }
+ uint64_t i;
+
+ for( i = 0 ; i < i_langid_len ; i = i + 2 )
+ {
+ s_lang_str[i/2] = GetWLE( var_buffer_get16( &buffer
) );
+ }
+ s_lang_str[i/2] = '\0';
+ hdr->tablang[i_current_id] = malloc( i/2 );
+ if( hdr->tablang[i_current_id] )
+ {
+ memcpy( hdr->tablang[i_current_id], s_lang_str,i/2
+ 1 );
+ }
+ free( s_lang_str );
+ }
+ }
+
else
{
// skip unknown guid
@@ -178,21 +221,41 @@ void asf_HeaderParse ( asf_header_t *hdr,
}
}
-void asf_StreamSelect ( asf_header_t *hdr,
+void asf_ClearCandidate ( asf_candidate_t *cell )
+{
+ asf_candidate_t * tmp;
+ while( cell->is_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->is_next = true;
+ work_Candidate->next = malloc( sizeof( asf_candidate_t ) );
+ if( !work_Candidate->next ) return work_Candidate;
+ work_Candidate = work_Candidate->next;
+ work_Candidate->is_next = false;
+ return work_Candidate;
+}
+
+void asf_StreamSelect ( asf_header_t *hdr,
int i_bitrate_max,
- bool b_all, bool b_audio, bool b_video )
+ bool b_all, bool b_audio, bool b_video ,
char * 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 +277,97 @@ 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 ) );
+ if( !head_Candidatefavlang ) return;
+ head_Candidatefavlang->is_next = false;
+ courant_Candidatefavlang = head_Candidatefavlang;
+
+ head_Candidateotherlang = malloc( sizeof( asf_candidate_t ) );
+ if( !head_Candidatefavlang ) return;
+ head_Candidateotherlang->is_next = false;
+ courant_Candidateotherlang = head_Candidateotherlang;
+
+ head_CandidateVideo = malloc( sizeof( asf_candidate_t ) );
+ if( !head_Candidatefavlang ) return;
+ head_CandidateVideo->is_next = false;
+ 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( lang != NULL && strcmp(
hdr->tablang[hdr->stream[i].i_lang_id], 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;
}
- 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 )
- ) ) ) )
+ /* video */
+ else if( hdr->stream[i].i_cat == ASF_CODEC_TYPE_VIDEO &&
b_video && ( 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->is_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->is_next )
+ {
+ while(courant_CandidateVideo->is_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..d13aacd 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,25 @@ typedef struct
int64_t i_file_size;
int64_t i_data_packets_count;
int32_t i_min_data_packet_size;
+ char * tablang[128];
asf_stream_t stream[128];
} asf_header_t;
+typedef struct asf_candidate_t
+{
+ int value ;
+ bool is_next ;
+ 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 , char * lang );
#endif
diff --git a/modules/access/mms/mmsh.c b/modules/access/mms/mmsh.c
index 2a36670..5758fa0 100644
--- a/modules/access/mms/mmsh.c
+++ b/modules/access/mms/mmsh.c
@@ -465,7 +465,8 @@ static int Reset( access_t *p_access )
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" ),
+ var_InheritString( p_access->p_parent,
"audio-language" ) );
/* Check we have comptible asfh */
for( i = 1; i < 128; i++ )
@@ -718,7 +719,8 @@ static int Describe( access_t *p_access, char
**ppsz_location )
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" ),
+ var_InheritString( p_access->p_parent,
"audio-language" ) );
return VLC_SUCCESS;
error:
diff --git a/modules/access/mms/mmstu.c b/modules/access/mms/mmstu.c
index 932c59f..5ac3355 100644
--- a/modules/access/mms/mmstu.c
+++ b/modules/access/mms/mmstu.c
@@ -792,7 +792,8 @@ static int MMSOpen( access_t *p_access, vlc_url_t
*p_url, int i_proto )
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" ),
+ var_InheritString( p_access->p_parent,
"audio-language" ) );
/* *** now select stream we want to receive *** */
/* TODO take care of stream bitrate TODO */
--
1.7.9.5
More information about the vlc-devel
mailing list