ignore this version patch please, the subject incorrect. > 在 2019年8月5日,上午10:26,Steven Liu <l...@chinaffmpeg.org> 写道: > > write mpegts or fmp4 context into buffer, and flush the buffer into > output file when split fragment. merge two format split workflow into > one workflow > > Signed-off-by: Steven Liu <l...@chinaffmpeg.org> > --- > libavformat/hlsenc.c | 251 +++++++++++++++++++++---------------------- > 1 file changed, 124 insertions(+), 127 deletions(-) > > diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c > index 51310fb528..f6f9c8161d 100644 > --- a/libavformat/hlsenc.c > +++ b/libavformat/hlsenc.c > @@ -815,7 +815,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream > *vs) > vs->start_pos = 0; > vs->new_start = 1; > > - if (hls->segment_type == SEGMENT_TYPE_FMP4) { > + if (hls->segment_type == SEGMENT_TYPE_FMP4 && hls->max_seg_size > 0) { > if (hls->http_persistent > 0) { > //TODO: Support fragment fmp4 for http persistent in HLS muxer. > av_log(s, AV_LOG_WARNING, "http persistent mode is currently > unsupported for fragment mp4 in the HLS muxer.\n"); > @@ -824,34 +824,38 @@ static int hls_mux_init(AVFormatContext *s, > VariantStream *vs) > av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently > unsupported in the HLS muxer.\n"); > return AVERROR_PATCHWELCOME; > } > + } > > - vs->packets_written = 0; > - vs->init_range_length = 0; > - set_http_options(s, &options, hls); > - if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) > - return ret; > + vs->packets_written = 0; > + vs->init_range_length = 0; > + set_http_options(s, &options, hls); > + if ((ret = avio_open_dyn_buf(&oc->pb)) < 0) > + return ret; > > + if (hls->segment_type == SEGMENT_TYPE_FMP4) { > if (byterange_mode) { > ret = hlsenc_io_open(s, &vs->out, vs->basename, &options); > } else { > ret = hlsenc_io_open(s, &vs->out, vs->base_output_dirname, > &options); > } > - av_dict_free(&options); > + } > + av_dict_free(&options); > + if (ret < 0) { > + av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", > vs->fmp4_init_filename); > + return ret; > + } > + > + if (hls->format_options_str) { > + ret = av_dict_parse_string(&hls->format_options, > hls->format_options_str, "=", ":", 0); > if (ret < 0) { > - av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", > vs->fmp4_init_filename); > + av_log(s, AV_LOG_ERROR, "Could not parse format options list > '%s'\n", > + hls->format_options_str); > return ret; > } > + } > > - if (hls->format_options_str) { > - ret = av_dict_parse_string(&hls->format_options, > hls->format_options_str, "=", ":", 0); > - if (ret < 0) { > - av_log(s, AV_LOG_ERROR, "Could not parse format options list > '%s'\n", > - hls->format_options_str); > - return ret; > - } > - } > - > - av_dict_copy(&options, hls->format_options, 0); > + av_dict_copy(&options, hls->format_options, 0); > + if (hls->segment_type == SEGMENT_TYPE_FMP4) { > av_dict_set(&options, "fflags", "-autobsf", 0); > av_dict_set(&options, "movflags", "+frag_custom+dash+delay_moov", > AV_DICT_APPEND); > ret = avformat_init_output(oc, &options); > @@ -862,9 +866,9 @@ static int hls_mux_init(AVFormatContext *s, VariantStream > *vs) > av_dict_free(&options); > return AVERROR(EINVAL); > } > - avio_flush(oc->pb); > - av_dict_free(&options); > } > + avio_flush(oc->pb); > + av_dict_free(&options); > return 0; > } > > @@ -1435,7 +1439,6 @@ static int hls_window(AVFormatContext *s, int last, > VariantStream *vs) > { > HLSContext *hls = s->priv_data; > HLSSegment *en; > - AVFormatContext *oc = vs->avf; > int target_duration = 0; > int ret = 0; > char temp_filename[MAX_URL_SIZE]; > @@ -1471,7 +1474,7 @@ static int hls_window(AVFormatContext *s, int last, > VariantStream *vs) > > set_http_options(s, &options, hls); > snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" : > "%s", vs->m3u8_name); > - if ((ret = hlsenc_io_open(s, (byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &oc->pb, temp_filename, &options)) < 0) > { > + if ((ret = hlsenc_io_open(s, (byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &vs->out, temp_filename, &options)) < > 0) { > if (hls->ignore_io_errors) > ret = 0; > goto fail; > @@ -1483,33 +1486,33 @@ static int hls_window(AVFormatContext *s, int last, > VariantStream *vs) > } > > vs->discontinuity_set = 0; > - ff_hls_write_playlist_header((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, hls->version, hls->allowcache, > + ff_hls_write_playlist_header((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, hls->version, hls->allowcache, > target_duration, sequence, hls->pl_type, > hls->flags & HLS_I_FRAMES_ONLY); > > if((hls->flags & HLS_DISCONT_START) && sequence==hls->start_sequence && > vs->discontinuity_set==0 ){ > - avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "#EXT-X-DISCONTINUITY\n"); > + avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, "#EXT-X-DISCONTINUITY\n"); > vs->discontinuity_set = 1; > } > if (vs->has_video && (hls->flags & HLS_INDEPENDENT_SEGMENTS)) { > - avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "#EXT-X-INDEPENDENT-SEGMENTS\n"); > + avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, > "#EXT-X-INDEPENDENT-SEGMENTS\n"); > } > for (en = vs->segments; en; en = en->next) { > if ((hls->encrypt || hls->key_info_file) && (!key_uri || > strcmp(en->key_uri, key_uri) || > av_strcasecmp(en->iv_string, iv_string))) > { > - avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, > "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); > + avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, > "#EXT-X-KEY:METHOD=AES-128,URI=\"%s\"", en->key_uri); > if (*en->iv_string) > - avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, ",IV=0x%s", en->iv_string); > - avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, "\n"); > + avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, ",IV=0x%s", en->iv_string); > + avio_printf((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, "\n"); > key_uri = en->key_uri; > iv_string = en->iv_string; > } > > if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == vs->segments)) > { > - ff_hls_write_init_file((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, (hls->flags & HLS_SINGLE_FILE) ? > en->filename : vs->fmp4_init_filename, > + ff_hls_write_init_file((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, (hls->flags & HLS_SINGLE_FILE) > ? en->filename : vs->fmp4_init_filename, > hls->flags & HLS_SINGLE_FILE, > vs->init_range_length, 0); > } > > - ret = ff_hls_write_file_entry((byterange_mode || hls->segment_type > == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb, en->discont, byterange_mode, > + ret = ff_hls_write_file_entry((byterange_mode || hls->segment_type > == SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out, en->discont, byterange_mode, > en->duration, hls->flags & > HLS_ROUND_DURATIONS, > en->size, en->pos, vs->baseurl, > en->filename, prog_date_time_p, > en->keyframe_size, en->keyframe_pos, hls->flags & HLS_I_FRAMES_ONLY); > @@ -1519,7 +1522,7 @@ static int hls_window(AVFormatContext *s, int last, > VariantStream *vs) > } > > if (last && (hls->flags & HLS_OMIT_ENDLIST)==0) > - ff_hls_write_end_list((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : oc->pb); > + ff_hls_write_end_list((byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? hls->m3u8_out : vs->out); > > if (vs->vtt_m3u8_name) { > snprintf(temp_vtt_filename, sizeof(temp_vtt_filename), use_temp_file > ? "%s.tmp" : "%s", vs->vtt_m3u8_name); > @@ -1546,7 +1549,7 @@ static int hls_window(AVFormatContext *s, int last, > VariantStream *vs) > > fail: > av_dict_free(&options); > - hlsenc_io_close(s, (byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &oc->pb, temp_filename); > + hlsenc_io_close(s, (byterange_mode || hls->segment_type == > SEGMENT_TYPE_FMP4) ? &hls->m3u8_out : &vs->out, temp_filename); > hlsenc_io_close(s, &hls->sub_m3u8_out, vs->vtt_m3u8_name); > if (use_temp_file) { > ff_rename(temp_filename, vs->m3u8_name, s); > @@ -1694,42 +1697,13 @@ static int hls_start(AVFormatContext *s, > VariantStream *vs) > } > c->encrypt_started = 1; > } > - if ((err = av_dict_set(&options, "encryption_key", c->key_string, 0)) > - < 0) > - goto fail; > err = av_strlcpy(iv_string, c->iv_string, sizeof(iv_string)); > - if (!err) > + if (!err) { > snprintf(iv_string, sizeof(iv_string), "%032"PRIx64, > vs->sequence); > - if ((err = av_dict_set(&options, "encryption_iv", iv_string, 0)) < 0) > - goto fail; > - > - filename = av_asprintf("crypto:%s", oc->url); > - if (!filename) { > - err = AVERROR(ENOMEM); > - goto fail; > - } > - err = hlsenc_io_open(s, &oc->pb, filename, &options); > - av_free(filename); > - av_dict_free(&options); > - if (err < 0) > - return err; > - } else if (c->segment_type != SEGMENT_TYPE_FMP4) { > - if ((err = hlsenc_io_open(s, &oc->pb, oc->url, &options)) < 0) { > - if (c->ignore_io_errors) > - err = 0; > - goto fail; > + memset(c->iv_string, 0, sizeof(c->iv_string)); > + memcpy(c->iv_string, iv_string, sizeof(iv_string)); > } > } > - if (vs->vtt_basename) { > - set_http_options(s, &options, c); > - if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < > 0) { > - if (c->ignore_io_errors) > - err = 0; > - goto fail; > - } > - } > - av_dict_free(&options); > - > if (c->segment_type != SEGMENT_TYPE_FMP4) { > /* We only require one PAT/PMT per segment. */ > if (oc->oformat->priv_class && oc->priv_data) { > @@ -1741,7 +1715,23 @@ static int hls_start(AVFormatContext *s, VariantStream > *vs) > av_opt_set(oc->priv_data, "sdt_period", period, 0); > av_opt_set(oc->priv_data, "pat_period", period, 0); > } > + if (c->flags & HLS_SINGLE_FILE) { > + if ((err = hlsenc_io_open(s, &vs->out, oc->url, &options)) < 0) { > + if (c->ignore_io_errors) > + err = 0; > + goto fail; > + } > + } > } > + if (vs->vtt_basename) { > + set_http_options(s, &options, c); > + if ((err = hlsenc_io_open(s, &vtt_oc->pb, vtt_oc->url, &options)) < > 0) { > + if (c->ignore_io_errors) > + err = 0; > + goto fail; > + } > + } > + av_dict_free(&options); > > if (vs->vtt_basename) { > err = avformat_write_header(vtt_oc,NULL); > @@ -2343,20 +2333,12 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > int64_t new_start_pos; > int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || > (hls->max_seg_size > 0); > > - av_write_frame(vs->avf, NULL); /* Flush any buffered data */ > - > - new_start_pos = avio_tell(vs->avf->pb); > - > - if (hls->segment_type != SEGMENT_TYPE_FMP4) { > - avio_flush(oc->pb); > - vs->size = new_start_pos - vs->start_pos; > - } else { > - vs->size = new_start_pos; > - } > - > + av_write_frame(oc, NULL); /* Flush any buffered data */ > + new_start_pos = avio_tell(oc->pb); > + vs->size = new_start_pos - vs->start_pos; > + avio_flush(oc->pb); > if (hls->segment_type == SEGMENT_TYPE_FMP4) { > if (!vs->init_range_length) { > - avio_flush(oc->pb); > range_length = avio_close_dyn_buf(oc->pb, &buffer); > avio_write(vs->out, buffer, range_length); > av_free(buffer); > @@ -2365,14 +2347,10 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > vs->packets_written = 0; > vs->start_pos = range_length; > if (!byterange_mode) { > - ff_format_io_close(s, &vs->out); > +// ff_format_io_close(s, &vs->out); > hlsenc_io_close(s, &vs->out, vs->base_output_dirname); > } > } > - } else { > - if (!byterange_mode) { > - hlsenc_io_close(s, &oc->pb, oc->url); > - } > } > if (!byterange_mode) { > if (vs->vtt_avf) { > @@ -2387,32 +2365,44 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > > // look to rename the asset name > if (use_temp_file) { > - if (!(hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size <= 0)) > - if ((vs->avf->oformat->priv_class && vs->avf->priv_data) && > hls->segment_type != SEGMENT_TYPE_FMP4) > - av_opt_set(vs->avf->priv_data, "mpegts_flags", > "resend_headers", 0); > + av_dict_set(&options, "mpegts_flags", "resend_headers", 0); > } > > - if (hls->segment_type == SEGMENT_TYPE_FMP4) { > - if (hls->flags & HLS_SINGLE_FILE) { > - ret = flush_dynbuf(vs, &range_length); > - if (ret < 0) { > - return ret; > + if (hls->flags & HLS_SINGLE_FILE) { > + ret = flush_dynbuf(vs, &range_length); > + if (ret < 0) { > + return ret; > + } > + vs->size = range_length; > + } else { > + set_http_options(s, &options, hls); > + if ((hls->max_seg_size > 0 && (vs->size >= hls->max_seg_size)) > || !byterange_mode) { > + char *filename = NULL; > + if (hls->key_info_file || hls->encrypt) { > + av_dict_set(&options, "encryption_key", hls->key_string, > 0); > + av_dict_set(&options, "encryption_iv", hls->iv_string, > 0); > + filename = av_asprintf("crypto:%s", oc->url); > + } else { > + filename = av_asprintf("%s", oc->url); > } > - vs->size = range_length; > - } else { > - set_http_options(s, &options, hls); > - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, &options); > + if (!filename) { > + return AVERROR(ENOMEM); > + } > + ret = hlsenc_io_open(s, &vs->out, filename, &options); > if (ret < 0) { > av_log(s, hls->ignore_io_errors ? AV_LOG_WARNING : > AV_LOG_ERROR, > - "Failed to open file '%s'\n", vs->avf->url); > + "Failed to open file '%s'\n", filename); > return hls->ignore_io_errors ? 0 : ret; > } > - write_styp(vs->out); > + if (hls->segment_type == SEGMENT_TYPE_FMP4) { > + write_styp(vs->out); > + } > ret = flush_dynbuf(vs, &range_length); > if (ret < 0) { > return ret; > } > - ff_format_io_close(s, &vs->out); > + hlsenc_io_close(s, &vs->out, filename); > + av_free(filename); > } > } > > @@ -2420,7 +2410,7 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > hls_rename_temp_file(s, oc); > } > > - old_filename = av_strdup(vs->avf->url); > + old_filename = av_strdup(oc->url); > if (!old_filename) { > return AVERROR(ENOMEM); > } > @@ -2435,11 +2425,6 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > } > } > > - if (hls->segment_type != SEGMENT_TYPE_FMP4) { > - vs->start_pos = new_start_pos; > - } else { > - vs->start_pos += vs->size; > - } > // if we're building a VOD playlist, skip writing the manifest > multiple times, and just wait until the end > if (hls->pl_type != PLAYLIST_TYPE_VOD) { > if ((ret = hls_window(s, 0, vs)) < 0) { > @@ -2449,8 +2434,10 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > > if (hls->flags & HLS_SINGLE_FILE) { > vs->number++; > + vs->start_pos += vs->size; > } else if (hls->max_seg_size > 0) { > - if (vs->start_pos >= hls->max_seg_size) { > + vs->start_pos = new_start_pos; > + if (vs->size >= hls->max_seg_size) { > vs->sequence++; > sls_flag_file_rename(hls, vs, old_filename); > ret = hls_start(s, vs); > @@ -2461,6 +2448,7 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > } > vs->number++; > } else { > + vs->start_pos = new_start_pos; > sls_flag_file_rename(hls, vs, old_filename); > ret = hls_start(s, vs); > } > @@ -2475,13 +2463,12 @@ static int hls_write_packet(AVFormatContext *s, > AVPacket *pkt) > vs->packets_written++; > if (oc->pb) { > ret = ff_write_chained(oc, stream_index, pkt, s, 0); > + vs->video_keyframe_size += pkt->size; > if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) && (pkt->flags & > AV_PKT_FLAG_KEY)) { > - vs->video_keyframe_size = avio_tell(oc->pb) - vs->video_lastpos; > - vs->video_keyframe_pos = vs->start_pos; > + vs->video_keyframe_size = avio_tell(oc->pb); > } else { > - vs->video_lastpos = avio_tell(oc->pb); > + vs->video_keyframe_pos = avio_tell(vs->out); > } > - > if (hls->ignore_io_errors) > ret = 0; > } > @@ -2530,10 +2517,12 @@ static int hls_write_trailer(struct AVFormatContext > *s) > int i; > int ret = 0; > VariantStream *vs = NULL; > + AVDictionary *options = NULL; > + int range_length, byterange_mode; > > for (i = 0; i < hls->nb_varstreams; i++) { > + char *filename = NULL; > vs = &hls->var_streams[i]; > - > oc = vs->avf; > vtt_oc = vs->vtt_avf; > old_filename = av_strdup(vs->avf->url); > @@ -2542,11 +2531,22 @@ static int hls_write_trailer(struct AVFormatContext > *s) > if (!old_filename) { > return AVERROR(ENOMEM); > } > + if (hls->key_info_file || hls->encrypt) { > + av_dict_set(&options, "encryption_key", hls->key_string, 0); > + av_dict_set(&options, "encryption_iv", hls->iv_string, 0); > + filename = av_asprintf("crypto:%s", vs->avf->url); > + } else { > + filename = av_asprintf("%s", vs->avf->url); > + } > + if (!filename) { > + return AVERROR(ENOMEM); > + } > + > + > if ( hls->segment_type == SEGMENT_TYPE_FMP4) { > int range_length = 0; > if (!vs->init_range_length) { > uint8_t *buffer = NULL; > - int range_length, byterange_mode; > av_write_frame(vs->avf, NULL); /* Flush any buffered data */ > avio_flush(oc->pb); > > @@ -2563,21 +2563,25 @@ static int hls_write_trailer(struct AVFormatContext > *s) > hlsenc_io_close(s, &vs->out, vs->base_output_dirname); > } > } > - if (!(hls->flags & HLS_SINGLE_FILE)) { > - ret = hlsenc_io_open(s, &vs->out, vs->avf->url, NULL); > - if (ret < 0) { > - av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", > vs->avf->url); > - goto failed; > - } > - write_styp(vs->out); > - } > - ret = flush_dynbuf(vs, &range_length); > + } > + if (!(hls->flags & HLS_SINGLE_FILE)) { > + set_http_options(s, &options, hls); > + ret = hlsenc_io_open(s, &vs->out, filename, &options); > if (ret < 0) { > + av_log(s, AV_LOG_ERROR, "Failed to open file '%s'\n", > vs->avf->url); > goto failed; > } > - vs->size = range_length; > - ff_format_io_close(s, &vs->out); > + if (hls->segment_type == SEGMENT_TYPE_FMP4) > + write_styp(vs->out); > } > + ret = flush_dynbuf(vs, &range_length); > + if (ret < 0) > + goto failed; > + > + vs->size = range_length; > + hlsenc_io_close(s, &vs->out, filename); > + av_free(filename); > + > > failed: > av_write_trailer(oc); > @@ -2587,12 +2591,6 @@ failed: > use_temp_file = proto && !strcmp(proto, "file") && (hls->flags & > HLS_TEMP_FILE); > } > > - if (oc->pb) { > - if (hls->segment_type != SEGMENT_TYPE_FMP4) { > - vs->size = avio_tell(vs->avf->pb) - vs->start_pos; > - hlsenc_io_close(s, &vs->avf->pb, vs->avf->url); > - } > - > // rename that segment from .tmp to the real one > if (use_temp_file && !(hls->flags & HLS_SINGLE_FILE)) { > hls_rename_temp_file(s, oc); > @@ -2606,7 +2604,6 @@ failed: > > /* after av_write_trailer, then duration + 1 duration per packet > */ > hls_append_segment(s, hls, vs, vs->duration + vs->dpp, > vs->start_pos, vs->size); > - } > > sls_flag_file_rename(hls, vs, old_filename); > > -- > 2.17.2 (Apple Git-113) > > > > _______________________________________________ > 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".