avformat/hlsenc: support fmp4 single file mode
add byterange mode of the hls fmp4 Reviewed-by: Derek Buitenhuis <derek.buitenhuis@gmail.com> Signed-off-by: Steven Liu <lq@onvideo.cn>
This commit is contained in:
		
							parent
							
								
									80bc648e77
								
							
						
					
					
						commit
						738b29cfb6
					
				@ -531,6 +531,7 @@ static int hls_mux_init(AVFormatContext *s)
 | 
			
		||||
    HLSContext *hls = s->priv_data;
 | 
			
		||||
    AVFormatContext *oc;
 | 
			
		||||
    AVFormatContext *vtt_oc = NULL;
 | 
			
		||||
    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
 | 
			
		||||
    int i, ret;
 | 
			
		||||
 | 
			
		||||
    ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL);
 | 
			
		||||
@ -584,7 +585,11 @@ static int hls_mux_init(AVFormatContext *s)
 | 
			
		||||
    hls->fmp4_init_mode = 0;
 | 
			
		||||
 | 
			
		||||
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 | 
			
		||||
        hls->fmp4_init_mode = 1;
 | 
			
		||||
        if (hls->max_seg_size > 0) {
 | 
			
		||||
            av_log(s, AV_LOG_WARNING, "Multi-file byterange mode is currently unsupported in the HLS muxer.\n");
 | 
			
		||||
            return AVERROR_PATCHWELCOME;
 | 
			
		||||
        }
 | 
			
		||||
        hls->fmp4_init_mode = !byterange_mode;
 | 
			
		||||
        if ((ret = s->io_open(s, &oc->pb, hls->base_output_dirname, AVIO_FLAG_WRITE, NULL)) < 0) {
 | 
			
		||||
            av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename);
 | 
			
		||||
            return ret;
 | 
			
		||||
@ -980,9 +985,6 @@ static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version
 | 
			
		||||
    }
 | 
			
		||||
    avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
 | 
			
		||||
    avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
 | 
			
		||||
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 | 
			
		||||
        avio_printf(out, "#EXT-X-MAP:URI=\"%s\"\n", hls->fmp4_init_filename);
 | 
			
		||||
    }
 | 
			
		||||
    av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1066,13 +1068,21 @@ static int hls_window(AVFormatContext *s, int last)
 | 
			
		||||
            avio_printf(out, "#EXT-X-DISCONTINUITY\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hls->flags & HLS_ROUND_DURATIONS)
 | 
			
		||||
            avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
 | 
			
		||||
        else
 | 
			
		||||
            avio_printf(out, "#EXTINF:%f,\n", en->duration);
 | 
			
		||||
        if (byterange_mode)
 | 
			
		||||
             avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
 | 
			
		||||
                         en->size, en->pos);
 | 
			
		||||
        if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments)) {
 | 
			
		||||
            avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", hls->fmp4_init_filename);
 | 
			
		||||
            if (hls->flags & HLS_SINGLE_FILE) {
 | 
			
		||||
                avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos);
 | 
			
		||||
            }
 | 
			
		||||
            avio_printf(out, "\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            if (hls->flags & HLS_ROUND_DURATIONS)
 | 
			
		||||
                avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
 | 
			
		||||
            else
 | 
			
		||||
                avio_printf(out, "#EXTINF:%f,\n", en->duration);
 | 
			
		||||
            if (byterange_mode)
 | 
			
		||||
                avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n",
 | 
			
		||||
                            en->size, en->pos);
 | 
			
		||||
        }
 | 
			
		||||
        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
 | 
			
		||||
            time_t tt, wrongsecs;
 | 
			
		||||
            int milli;
 | 
			
		||||
@ -1097,9 +1107,11 @@ static int hls_window(AVFormatContext *s, int last)
 | 
			
		||||
            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
 | 
			
		||||
            prog_date_time += en->duration;
 | 
			
		||||
        }
 | 
			
		||||
        if (hls->baseurl)
 | 
			
		||||
            avio_printf(out, "%s", hls->baseurl);
 | 
			
		||||
        avio_printf(out, "%s\n", en->filename);
 | 
			
		||||
        if (!((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments))) {
 | 
			
		||||
            if (hls->baseurl)
 | 
			
		||||
                avio_printf(out, "%s", hls->baseurl);
 | 
			
		||||
            avio_printf(out, "%s\n", en->filename);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
 | 
			
		||||
@ -1262,7 +1274,7 @@ static int hls_start(AVFormatContext *s)
 | 
			
		||||
    }
 | 
			
		||||
    av_dict_free(&options);
 | 
			
		||||
 | 
			
		||||
    if (c->segment_type == SEGMENT_TYPE_FMP4) {
 | 
			
		||||
    if (c->segment_type == SEGMENT_TYPE_FMP4 && !(c->flags & HLS_SINGLE_FILE)) {
 | 
			
		||||
            write_styp(oc->pb);
 | 
			
		||||
    } else {
 | 
			
		||||
        /* We only require one PAT/PMT per segment. */
 | 
			
		||||
@ -1315,15 +1327,10 @@ static int hls_write_header(AVFormatContext *s)
 | 
			
		||||
    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);
 | 
			
		||||
    const char *vtt_pattern = "%d.vtt";
 | 
			
		||||
    AVDictionary *options = NULL;
 | 
			
		||||
    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
 | 
			
		||||
    int basename_size;
 | 
			
		||||
    int vtt_basename_size;
 | 
			
		||||
 | 
			
		||||
    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 | 
			
		||||
        if (byterange_mode) {
 | 
			
		||||
            av_log(s, AV_LOG_WARNING, "Have not support fmp4 byterange mode yet now\n");
 | 
			
		||||
            return AVERROR_PATCHWELCOME;
 | 
			
		||||
        }
 | 
			
		||||
        pattern = "%d.m4s";
 | 
			
		||||
    }
 | 
			
		||||
    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||
 | 
			
		||||
@ -1400,8 +1407,13 @@ static int hls_write_header(AVFormatContext *s)
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (hls->flags & HLS_SINGLE_FILE)
 | 
			
		||||
            pattern = ".ts";
 | 
			
		||||
        if (hls->flags & HLS_SINGLE_FILE) {
 | 
			
		||||
            if (hls->segment_type == SEGMENT_TYPE_FMP4) {
 | 
			
		||||
                pattern = ".m4s";
 | 
			
		||||
            } else {
 | 
			
		||||
                pattern = ".ts";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (hls->use_localtime) {
 | 
			
		||||
            basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
 | 
			
		||||
@ -1490,6 +1502,14 @@ static int hls_write_header(AVFormatContext *s)
 | 
			
		||||
        av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
 | 
			
		||||
        hls->fmp4_init_filename  = av_strdup(hls->basename);
 | 
			
		||||
        if (!hls->fmp4_init_filename) {
 | 
			
		||||
            ret = AVERROR(ENOMEM);
 | 
			
		||||
            goto fail;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((ret = hls_mux_init(s)) < 0)
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
@ -1504,7 +1524,7 @@ static int hls_write_header(AVFormatContext *s)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (hls->segment_type != SEGMENT_TYPE_FMP4) {
 | 
			
		||||
    if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {
 | 
			
		||||
        if ((ret = hls_start(s)) < 0)
 | 
			
		||||
            goto fail;
 | 
			
		||||
    }
 | 
			
		||||
@ -1545,6 +1565,7 @@ fail:
 | 
			
		||||
 | 
			
		||||
    av_dict_free(&options);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        av_freep(&hls->fmp4_init_filename);
 | 
			
		||||
        av_freep(&hls->basename);
 | 
			
		||||
        av_freep(&hls->vtt_basename);
 | 
			
		||||
        av_freep(&hls->key_basename);
 | 
			
		||||
@ -1643,7 +1664,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
 | 
			
		||||
            hls->number--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!hls->fmp4_init_mode)
 | 
			
		||||
        if (!hls->fmp4_init_mode || byterange_mode)
 | 
			
		||||
            ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
 | 
			
		||||
 | 
			
		||||
        hls->start_pos = new_start_pos;
 | 
			
		||||
@ -1679,9 +1700,10 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ((ret = hls_window(s, 0)) < 0) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        if (!hls->fmp4_init_mode || byterange_mode)
 | 
			
		||||
            if ((ret = hls_window(s, 0)) < 0) {
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = ff_write_chained(oc, stream_index, pkt, s, 0);
 | 
			
		||||
@ -1722,6 +1744,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
 | 
			
		||||
        hls->size = avio_tell(hls->vtt_avf->pb) - hls->start_pos;
 | 
			
		||||
        ff_format_io_close(s, &vtt_oc->pb);
 | 
			
		||||
    }
 | 
			
		||||
    av_freep(&hls->fmp4_init_filename);
 | 
			
		||||
    av_freep(&hls->basename);
 | 
			
		||||
    av_freep(&hls->base_output_dirname);
 | 
			
		||||
    av_freep(&hls->key_basename);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user