Le dim. 7 avr. 2024 à 05:44, Steven Liu <lingjiujia...@gmail.com> a écrit :
> Romain Beauxis <to...@rastageeks.org> 于2024年3月26日周二 08:58写道: > > > > This patch adds support for updating HLS metadata passed as ID3 frames. > > > > This seems like a pretty straight-forward improvement. Updating the > > metadaata of the first stream seems to be the mechanism is other places > > in the code and works as expected. > > > > --- > > libavformat/hls.c | 54 ++++++++++++++++++++++++++++------------------- > > 1 file changed, 32 insertions(+), 22 deletions(-) > > > > diff --git a/libavformat/hls.c b/libavformat/hls.c > > index f6b44c2e35..ba6634d57a 100644 > > --- a/libavformat/hls.c > > +++ b/libavformat/hls.c > > @@ -93,6 +93,12 @@ enum PlaylistType { > > PLS_TYPE_VOD > > }; > > > > +#define ID3_PRIV_OWNER_TS "com.apple.streaming.transportStreamTimestamp" > > +#define ID3_PRIV_OWNER_AUDIO_SETUP > "com.apple.streaming.audioDescription" > > + > > +#define ID3v2_PRIV_OWNER_TS ID3v2_PRIV_METADATA_PREFIX ID3_PRIV_OWNER_TS > > +#define ID3v2_PRIV_OWNER_AUDIO_SETUP ID3v2_PRIV_METADATA_PREFIX > ID3_PRIV_OWNER_AUDIO_SETUP > > + > > /* > > * Each playlist has its own demuxer. If it currently is active, > > * it has an open AVIOContext too, and potentially an AVPacket > > @@ -150,9 +156,7 @@ struct playlist { > > int64_t id3_offset; /* in stream original tb */ > > uint8_t* id3_buf; /* temp buffer for id3 parsing */ > > unsigned int id3_buf_size; > > - AVDictionary *id3_initial; /* data from first id3 tag */ > > - int id3_found; /* ID3 tag found at some point */ > > - int id3_changed; /* ID3 tag data has changed at some point */ > > + AVDictionary *last_id3; /* data from the last id3 tag */ > > ID3v2ExtraMeta *id3_deferred_extra; /* stored here until subdemuxer > is opened */ > > > > HLSAudioSetupInfo audio_setup_info; > > @@ -270,7 +274,7 @@ static void free_playlist_list(HLSContext *c) > > av_freep(&pls->main_streams); > > av_freep(&pls->renditions); > > av_freep(&pls->id3_buf); > > - av_dict_free(&pls->id3_initial); > > + av_dict_free(&pls->last_id3); > > ff_id3v2_free_extra_meta(&pls->id3_deferred_extra); > > av_freep(&pls->init_sec_buf); > > av_packet_free(&pls->pkt); > > @@ -1083,15 +1087,13 @@ static void parse_id3(AVFormatContext *s, > AVIOContext *pb, > > AVDictionary **metadata, int64_t *dts, > HLSAudioSetupInfo *audio_setup_info, > > ID3v2ExtraMetaAPIC **apic, ID3v2ExtraMeta > **extra_meta) > > { > > - static const char id3_priv_owner_ts[] = > "com.apple.streaming.transportStreamTimestamp"; > > - static const char id3_priv_owner_audio_setup[] = > "com.apple.streaming.audioDescription"; > > ID3v2ExtraMeta *meta; > > > > ff_id3v2_read_dict(pb, metadata, ID3v2_DEFAULT_MAGIC, extra_meta); > > for (meta = *extra_meta; meta; meta = meta->next) { > > if (!strcmp(meta->tag, "PRIV")) { > > ID3v2ExtraMetaPRIV *priv = &meta->data.priv; > > - if (priv->datasize == 8 && !av_strncasecmp(priv->owner, > id3_priv_owner_ts, 44)) { > > + if (priv->datasize == 8 && !av_strncasecmp(priv->owner, > ID3_PRIV_OWNER_TS, strlen(ID3_PRIV_OWNER_TS))) { > > /* 33-bit MPEG timestamp */ > > int64_t ts = AV_RB64(priv->data); > > av_log(s, AV_LOG_DEBUG, "HLS ID3 audio timestamp > %"PRId64"\n", ts); > > @@ -1099,7 +1101,9 @@ static void parse_id3(AVFormatContext *s, > AVIOContext *pb, > > *dts = ts; > > else > > av_log(s, AV_LOG_ERROR, "Invalid HLS ID3 audio > timestamp %"PRId64"\n", ts); > > - } else if (priv->datasize >= 8 && > !av_strncasecmp(priv->owner, id3_priv_owner_audio_setup, 36)) { > > + } else if (priv->datasize >= 8 && > > + !av_strncasecmp(priv->owner, > ID3_PRIV_OWNER_AUDIO_SETUP, 36) && > > + audio_setup_info) { > > ff_hls_senc_read_audio_setup_info(audio_setup_info, > priv->data, priv->datasize); > > } > > } else if (!strcmp(meta->tag, "APIC") && apic) > > @@ -1113,9 +1117,10 @@ static int id3_has_changed_values(struct playlist > *pls, AVDictionary *metadata, > > { > > const AVDictionaryEntry *entry = NULL; > > const AVDictionaryEntry *oldentry; > > + > > /* check that no keys have changed values */ > > while ((entry = av_dict_iterate(metadata, entry))) { > > - oldentry = av_dict_get(pls->id3_initial, entry->key, NULL, > AV_DICT_MATCH_CASE); > > + oldentry = av_dict_get(pls->last_id3, entry->key, NULL, > AV_DICT_MATCH_CASE); > > if (!oldentry || strcmp(oldentry->value, entry->value) != 0) > > return 1; > > } > > @@ -1143,35 +1148,40 @@ static void handle_id3(AVIOContext *pb, struct > playlist *pls) > > ID3v2ExtraMetaAPIC *apic = NULL; > > ID3v2ExtraMeta *extra_meta = NULL; > > int64_t timestamp = AV_NOPTS_VALUE; > > + // Only set audio_setup_info on first id3 chunk. > > + HLSAudioSetupInfo *audio_setup_info = pls->last_id3 ? NULL : > &pls->audio_setup_info; > > > > - parse_id3(pls->ctx, pb, &metadata, ×tamp, > &pls->audio_setup_info, &apic, &extra_meta); > > + parse_id3(pls->ctx, pb, &metadata, ×tamp, audio_setup_info, > &apic, &extra_meta); > > > > - if (timestamp != AV_NOPTS_VALUE) { > > + if (pls->id3_mpegts_timestamp == AV_NOPTS_VALUE && timestamp != > AV_NOPTS_VALUE) { > > pls->id3_mpegts_timestamp = timestamp; > > pls->id3_offset = 0; > > } > > > > - if (!pls->id3_found) { > > - /* initial ID3 tags */ > > - av_assert0(!pls->id3_deferred_extra); > > - pls->id3_found = 1; > > - > > + if (id3_has_changed_values(pls, metadata, apic)) { > > /* get picture attachment and set text metadata */ > > if (pls->ctx->nb_streams) > > ff_id3v2_parse_apic(pls->ctx, extra_meta); > > - else > > + else { > > + av_assert0(!pls->id3_deferred_extra); > > /* demuxer not yet opened, defer picture attachment */ > > pls->id3_deferred_extra = extra_meta; > > + } > > > > ff_id3v2_parse_priv_dict(&metadata, extra_meta); > > + > > + av_dict_set(&metadata, ID3v2_PRIV_OWNER_TS, NULL, 0); > > + av_dict_set(&metadata, ID3v2_PRIV_OWNER_AUDIO_SETUP, NULL, 0); > > + > > + av_dict_free(&pls->ctx->metadata); > > av_dict_copy(&pls->ctx->metadata, metadata, 0); > > - pls->id3_initial = metadata; > > > > + if (pls->n_main_streams) > > + av_dict_copy(&pls->main_streams[0]->metadata, metadata, 0); > > + > > + if (pls->last_id3) av_dict_free(&pls->last_id3); > > + pls->last_id3 = metadata; > > } else { > > - if (!pls->id3_changed && id3_has_changed_values(pls, metadata, > apic)) { > > - avpriv_report_missing_feature(pls->parent, "Changing ID3 > metadata in HLS audio elementary stream"); > > - pls->id3_changed = 1; > > - } > > av_dict_free(&metadata); > > } > > > > -- > > 2.39.3 (Apple Git-145) > > > > _______________________________________________ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > I look at the second patch result: > > make: *** [fate-hls-adts-meta-demux] Error 1 > cpu_flags(raw) = 0x000813DB > cpu_flags_str(raw) = mmx mmxext sse sse2 sse3 ssse3 sse4.1 sse4.2 cmov > aesni > cpu_flags(effective) = 0x000813DB > cpu_flags_str(effective) = mmx mmxext sse sse2 sse3 ssse3 sse4.1 > sse4.2 cmov aesni > threads = 1 (cpu_count = 5) > make: Target 'fate' not remade because of errors. > > > > > https://patchwork.ffmpeg.org/project/ffmpeg/patch/20240326005639.27000-2-to...@rastageeks.org/ > > Ok. The samples are here: https://www.dropbox.com/scl/fo/1x74ztoa6yo9q49ignfnt/h?rlkey=xvg5nhgjr515gm6b375evm8n4&dl=0 If you place them under $FATE_SAMPLES/hls-adts-meta the test suite should pass. Are you the right person to also upload the samples? Thanks for your time on this! > > Thanks > Steven > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".