@@ -69,7 +69,6 @@ typedef struct {
6969 uint8_t key_cache [HLS_KEY_CACHE_SIZE ];
7070 uint8_t key_size ;
7171 hls_stream_key_t key ;
72- uint64_t sequence_no ;
7372 esp_aes_context aes_ctx ;
7473 bool aes_used ;
7574} http_stream_hls_key_t ;
@@ -96,14 +95,17 @@ typedef struct http_stream {
9695 bool gzip_encoding ; /* Content is encoded */
9796 gzip_miniz_handle_t gzip ; /* GZIP instance */
9897 http_stream_hls_key_t * hls_key ;
98+ uint64_t hls_sequence_no ;
9999 hls_handle_t * hls_media ;
100+ int url_index ;
100101 int request_range_size ;
101102 int64_t request_range_end ;
102103 bool is_last_range ;
103104 const char * user_agent ;
104105} http_stream_t ;
105106
106107static esp_err_t http_stream_auto_connect_next_track (audio_element_handle_t el );
108+ static int _update_hls_info (http_stream_t * http );
107109
108110// `errno` is not thread safe in multiple HTTP-clients,
109111// so it is necessary to save the errno number of HTTP clients to avoid reading and writing exceptions of HTTP-clients caused by errno exceptions
@@ -272,14 +274,13 @@ static esp_err_t _prepare_crypt(http_stream_t *http)
272274 if (ret < 0 ) {
273275 return ESP_FAIL ;
274276 }
275- ret = hls_playlist_get_key (http -> hls_media , http -> hls_key -> sequence_no , & http -> hls_key -> key );
277+ ret = hls_playlist_get_key (http -> hls_media , http -> hls_sequence_no , & http -> hls_key -> key );
276278 if (ret != 0 ) {
277279 return ESP_FAIL ;
278280 }
279281 esp_aes_init (& hls_key -> aes_ctx );
280282 esp_aes_setkey (& hls_key -> aes_ctx , (unsigned char * )hls_key -> key .key , 128 );
281283 hls_key -> aes_used = true;
282- http -> hls_key -> sequence_no ++ ;
283284 return ESP_OK ;
284285}
285286
@@ -387,6 +388,15 @@ static esp_err_t _resolve_playlist(audio_element_handle_t self, const char *uri)
387388 }
388389 } while (0 );
389390 if (hls ) {
391+ http -> hls_sequence_no = hls_playlist_get_sequence_no (hls );
392+ for (int i = 0 ; i < http -> url_index ; i ++ ) {
393+ char * next_url = http_playlist_get_next_track (http -> playlist );
394+ if (next_url == NULL ) {
395+ ESP_LOGE (TAG , "Url index %d over limited %d" , http -> url_index , i );
396+ return ESP_FAIL ;
397+ }
398+ }
399+ http -> hls_sequence_no += http -> url_index ;
390400 if (hls_playlist_is_encrypt (hls ) == false) {
391401 _free_hls_key (http );
392402 hls_playlist_close (hls );
@@ -398,27 +408,9 @@ static esp_err_t _resolve_playlist(audio_element_handle_t self, const char *uri)
398408 ESP_LOGE (TAG , "Hls do not have key url" );
399409 return ESP_FAIL ;
400410 }
401- if (http -> hls_key == NULL ) {
402- http -> hls_key = (http_stream_hls_key_t * ) calloc (1 , sizeof (http_stream_hls_key_t ));
403- if (http -> hls_key == NULL ) {
404- ESP_LOGE (TAG , "No memory for hls key" );
405- return ESP_FAIL ;
406- }
407- }
408- if (http -> hls_key -> key_url && strcmp (http -> hls_key -> key_url , key_url ) == 0 ) {
409- http -> hls_key -> key_loaded = true;
410- } else {
411- if (http -> hls_key -> key_url ) {
412- audio_free (http -> hls_key -> key_url );
413- }
414- http -> hls_key -> key_loaded = false;
415- http -> hls_key -> key_url = audio_strdup (key_url );
416- if (http -> hls_key -> key_url == NULL ) {
417- ESP_LOGE (TAG , "No memory for hls key url" );
418- return ESP_FAIL ;
419- }
411+ if (_update_hls_info (http ) != ESP_OK ) {
412+ return ESP_FAIL ;
420413 }
421- http -> hls_key -> sequence_no = hls_playlist_get_sequence_no (hls );
422414 }
423415 }
424416 return http -> is_valid_playlist ? ESP_OK : ESP_FAIL ;
@@ -570,7 +562,7 @@ static esp_err_t _http_open(audio_element_handle_t self)
570562 ESP_LOGE (TAG , "Error open connection, uri = NULL" );
571563 return ESP_FAIL ;
572564 }
573-
565+
574566 ESP_LOGD (TAG , "URI=%s" , uri );
575567 // if not initialize http client, initial it
576568 if (http -> client == NULL ) {
@@ -600,7 +592,7 @@ static esp_err_t _http_open(audio_element_handle_t self)
600592 return ESP_FAIL ;
601593 }
602594
603- if (_is_playlist (& info , uri ) == true) {
595+ if (_is_playlist (& info , uri ) == true && http -> is_playlist_resolved == false ) {
604596 /**
605597 * `goto _stream_open_begin` blocks on http_open until it gets valid URL.
606598 * Ensure that the stop command is processed
@@ -704,6 +696,43 @@ static bool _check_range_done(audio_element_handle_t self)
704696 return last_range ;
705697}
706698
699+ static int _update_hls_info (http_stream_t * http )
700+ {
701+ char * key_url = hls_playlist_get_key_uri_by_seq (http -> hls_media , http -> hls_sequence_no );
702+ if (key_url && http -> hls_key == NULL ) {
703+ http -> hls_key = audio_calloc (1 , sizeof (http_stream_hls_key_t ));
704+ if (http -> hls_key == NULL ) {
705+ ESP_LOGE (TAG , "No mem for HLS key" );
706+ return ESP_FAIL ;
707+ }
708+ }
709+ if (http -> hls_key ) {
710+ if (key_url == NULL ) {
711+ ESP_LOGE (TAG , "Hls do not have key url" );
712+ return ESP_FAIL ;
713+ }
714+ // Same key no need reload
715+ if (http -> hls_key -> key_url && strcmp (http -> hls_key -> key_url , key_url ) == 0 ) {
716+ http -> hls_key -> key_loaded = true;
717+ audio_free (key_url );
718+ } else {
719+ if (http -> hls_key -> key_url ) {
720+ audio_free (http -> hls_key -> key_url );
721+ }
722+ http -> hls_key -> key_loaded = false;
723+ http -> hls_key -> key_url = key_url ;
724+ }
725+ }
726+ return ESP_OK ;
727+ }
728+
729+ static int _update_next_hls_info (http_stream_t * http )
730+ {
731+ // Check HLS key need update or not
732+ http -> hls_sequence_no ++ ;
733+ return _update_hls_info (http );
734+ }
735+
707736static int _http_read (audio_element_handle_t self , char * buffer , int len , TickType_t ticks_to_wait , void * context )
708737{
709738 http_stream_t * http = (http_stream_t * )audio_element_getdata (self );
@@ -719,6 +748,9 @@ static int _http_read(audio_element_handle_t self, char *buffer, int len, TickTy
719748 rlen = _http_read_data (http , buffer , len );
720749 }
721750 }
751+ if (rlen <= 0 ) {
752+ _update_next_hls_info (http );
753+ }
722754 if (rlen <= 0 && http -> auto_connect_next_track ) {
723755 if (http_stream_auto_connect_next_track (self ) == ESP_OK ) {
724756 rlen = _http_read_data (http , buffer , len );
@@ -727,7 +759,7 @@ static int _http_read(audio_element_handle_t self, char *buffer, int len, TickTy
727759 if (rlen <= 0 ) {
728760 http -> _errno = esp_http_client_get_errno (http -> client );
729761 ESP_LOGW (TAG , "No more data,errno:%d, total_bytes:%llu, rlen = %d" , http -> _errno , info .byte_pos , rlen );
730- if (http -> _errno != 0 ) { // Error occuered , reset connection
762+ if (http -> _errno != 0 ) { // Error occurs , reset connection
731763 ESP_LOGW (TAG , "Got %d errno(%s)" , http -> _errno , strerror (http -> _errno ));
732764 return http -> _errno ;
733765 }
@@ -745,8 +777,8 @@ static int _http_read(audio_element_handle_t self, char *buffer, int len, TickTy
745777 return ESP_OK ;
746778 } else {
747779 if (http -> hls_key ) {
748- int ret = esp_aes_crypt_cbc (& http -> hls_key -> aes_ctx , ESP_AES_DECRYPT ,
749- rlen , (unsigned char * )http -> hls_key -> key .iv ,
780+ int ret = esp_aes_crypt_cbc (& http -> hls_key -> aes_ctx , ESP_AES_DECRYPT ,
781+ rlen , (unsigned char * )http -> hls_key -> key .iv ,
750782 (unsigned char * )buffer , (unsigned char * )buffer );
751783 if (rlen % 16 != 0 ) {
752784 ESP_LOGE (TAG , "Data length %d not aligned" , rlen );
@@ -873,6 +905,7 @@ audio_element_handle_t http_stream_init(http_stream_cfg_t *config)
873905 http -> user_data = config -> user_data ;
874906 http -> cert_pem = config -> cert_pem ;
875907 http -> user_agent = config -> user_agent ;
908+ http -> url_index = config -> url_index ;
876909
877910 if (config -> crt_bundle_attach ) {
878911#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL (4 , 3 , 0 ))
@@ -971,6 +1004,19 @@ esp_err_t http_stream_auto_connect_next_track(audio_element_handle_t el)
9711004 return ESP_FAIL ;
9721005}
9731006
1007+ esp_err_t http_stream_get_url_index (audio_element_handle_t el , int * url_idx )
1008+ {
1009+ http_stream_t * http = (http_stream_t * )audio_element_getdata (el );
1010+ if (http -> playlist == NULL || http -> hls_media == NULL || http -> playlist -> is_incomplete ) {
1011+ ESP_LOGI (TAG , "Only support for VOD HLS stream" );
1012+ return ESP_ERR_NOT_SUPPORTED ;
1013+ }
1014+ uint64_t start_seq = hls_playlist_get_sequence_no (http -> hls_media );
1015+ * (url_idx ) = (int )(http -> hls_sequence_no - start_seq );
1016+ ESP_LOGI (TAG , "Current url index %d\n" , * (url_idx ));
1017+ return ESP_OK ;
1018+ }
1019+
9741020esp_err_t http_stream_fetch_again (audio_element_handle_t el )
9751021{
9761022 http_stream_t * http = (http_stream_t * )audio_element_getdata (el );
0 commit comments