X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fsegment.c;h=24490f12806e2af267c8e811f37e05eb1928557c;hb=2606c48391377681541111263de41c79adeffa49;hp=858ccf86975c2cdfb3708824f8c133480c5c8ee1;hpb=936d967871562e36e307126b59e4e6bbb3a3bab7;p=ffmpeg diff --git a/libavformat/segment.c b/libavformat/segment.c index 858ccf86975..24490f12806 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -72,7 +72,7 @@ typedef struct SegmentContext { int segment_idx_wrap; ///< number after which the index wraps int segment_idx_wrap_nb; ///< number of time the index has wraped int segment_count; ///< number of segment files already written - ff_const59 AVOutputFormat *oformat; + const AVOutputFormat *oformat; AVFormatContext *avf; char *format; ///< format to use for output segment files AVDictionary *format_options; @@ -80,6 +80,7 @@ typedef struct SegmentContext { int list_flags; ///< flags affecting list generation int list_size; ///< number of entries for the segment list file + int is_nullctx; ///< whether avf->pb is a nullctx int use_clocktime; ///< flag to cut segments at regular clock time int64_t clocktime_offset; //< clock offset for cutting the segments at regular clock time int64_t clocktime_wrap_duration; //< wrapping duration considered for starting a new segment @@ -166,8 +167,10 @@ static int segment_mux_init(AVFormatContext *s) if (!(st = avformat_new_stream(oc, NULL))) return AVERROR(ENOMEM); + ret = ff_stream_encode_params_copy(st, ist); + if (ret < 0) + return ret; opar = st->codecpar; - avcodec_parameters_copy(opar, ipar); if (!oc->oformat->codec_tag || av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id || av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) { @@ -175,17 +178,6 @@ static int segment_mux_init(AVFormatContext *s) } else { opar->codec_tag = 0; } - st->sample_aspect_ratio = ist->sample_aspect_ratio; - st->time_base = ist->time_base; - st->avg_frame_rate = ist->avg_frame_rate; - st->disposition = ist->disposition; -#if FF_API_LAVF_AVCTX -FF_DISABLE_DEPRECATION_WARNINGS - if (ipar->codec_tag == MKTAG('t','m','c','d')) - st->codec->time_base = ist->codec->time_base; -FF_ENABLE_DEPRECATION_WARNINGS -#endif - av_dict_copy(&st->metadata, ist->metadata, 0); } return 0; @@ -509,7 +501,7 @@ static int parse_times(void *log_ctx, int64_t **times, int *nb_times, /* check on monotonicity */ if (i && (*times)[i-1] > (*times)[i]) { av_log(log_ctx, AV_LOG_ERROR, - "Specified time %f is greater than the following time %f\n", + "Specified time %f is smaller than the last time %f\n", (float)((*times)[i])/1000000, (float)((*times)[i-1])/1000000); FAIL(AVERROR(EINVAL)); } @@ -523,60 +515,52 @@ end: static int parse_frames(void *log_ctx, int **frames, int *nb_frames, const char *frames_str) { - char *p; - int i, ret = 0; - char *frames_str1 = av_strdup(frames_str); - char *saveptr = NULL; - - if (!frames_str1) - return AVERROR(ENOMEM); - -#define FAIL(err) ret = err; goto end + const char *p; + int i; *nb_frames = 1; - for (p = frames_str1; *p; p++) + for (p = frames_str; *p; p++) if (*p == ',') (*nb_frames)++; *frames = av_malloc_array(*nb_frames, sizeof(**frames)); if (!*frames) { av_log(log_ctx, AV_LOG_ERROR, "Could not allocate forced frames array\n"); - FAIL(AVERROR(ENOMEM)); + return AVERROR(ENOMEM); } - p = frames_str1; + p = frames_str; for (i = 0; i < *nb_frames; i++) { long int f; char *tailptr; - char *fstr = av_strtok(p, ",", &saveptr); - p = NULL; - if (!fstr) { + if (*p == '\0' || *p == ',') { av_log(log_ctx, AV_LOG_ERROR, "Empty frame specification in frame list %s\n", frames_str); - FAIL(AVERROR(EINVAL)); + return AVERROR(EINVAL); } - f = strtol(fstr, &tailptr, 10); - if (*tailptr || f <= 0 || f >= INT_MAX) { + f = strtol(p, &tailptr, 10); + if (*tailptr != '\0' && *tailptr != ',' || f <= 0 || f >= INT_MAX) { av_log(log_ctx, AV_LOG_ERROR, - "Invalid argument '%s', must be a positive integer <= INT64_MAX\n", - fstr); - FAIL(AVERROR(EINVAL)); + "Invalid argument '%s', must be a positive integer < INT_MAX\n", + p); + return AVERROR(EINVAL); } + if (*tailptr == ',') + tailptr++; + p = tailptr; (*frames)[i] = f; /* check on monotonicity */ if (i && (*frames)[i-1] > (*frames)[i]) { av_log(log_ctx, AV_LOG_ERROR, - "Specified frame %d is greater than the following frame %d\n", + "Specified frame %d is smaller than the last frame %d\n", (*frames)[i], (*frames)[i-1]); - FAIL(AVERROR(EINVAL)); + return AVERROR(EINVAL); } } -end: - av_free(frames_str1); - return ret; + return 0; } static int open_null_ctx(AVIOContext **ctx) @@ -659,11 +643,28 @@ static int select_reference_stream(AVFormatContext *s) static void seg_free(AVFormatContext *s) { SegmentContext *seg = s->priv_data; + SegmentListEntry *cur; + ff_format_io_close(s, &seg->list_pb); - avformat_free_context(seg->avf); - seg->avf = NULL; + if (seg->avf) { + if (seg->is_nullctx) + close_null_ctxp(&seg->avf->pb); + else + ff_format_io_close(s, &seg->avf->pb); + avformat_free_context(seg->avf); + seg->avf = NULL; + } av_freep(&seg->times); av_freep(&seg->frames); + av_freep(&seg->cur_entry.filename); + + cur = seg->segment_list_entries; + while (cur) { + SegmentListEntry *next = cur->next; + av_freep(&cur->filename); + av_free(cur); + cur = next; + } } static int seg_init(AVFormatContext *s) @@ -766,6 +767,7 @@ static int seg_init(AVFormatContext *s) } else { if ((ret = open_null_ctx(&oc->pb)) < 0) return ret; + seg->is_nullctx = 1; } av_dict_copy(&options, seg->format_options, 0); @@ -780,7 +782,6 @@ static int seg_init(AVFormatContext *s) av_dict_free(&options); if (ret < 0) { - ff_format_io_close(oc, &oc->pb); return ret; } seg->segment_frame_count = 0; @@ -823,6 +824,7 @@ static int seg_write_header(AVFormatContext *s) ff_format_io_close(oc, &oc->pb); } else { close_null_ctxp(&oc->pb); + seg->is_nullctx = 0; } if ((ret = oc->io_open(oc, &oc->pb, oc->url, AVIO_FLAG_WRITE, NULL)) < 0) return ret; @@ -848,7 +850,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); if (!st->codecpar->extradata_size) { - int pkt_extradata_size; + size_t pkt_extradata_size; uint8_t *pkt_extradata = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &pkt_extradata_size); if (pkt_extradata && pkt_extradata_size > 0) { ret = ff_alloc_extradata(st->codecpar, pkt_extradata_size); @@ -962,39 +964,21 @@ static int seg_write_trailer(struct AVFormatContext *s) { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; - SegmentListEntry *cur, *next; - int ret = 0; + int ret; if (!oc) - goto fail; + return 0; if (!seg->write_header_trailer) { if ((ret = segment_end(s, 0, 1)) < 0) - goto fail; + return ret; if ((ret = open_null_ctx(&oc->pb)) < 0) - goto fail; + return ret; + seg->is_nullctx = 1; ret = av_write_trailer(oc); - close_null_ctxp(&oc->pb); } else { ret = segment_end(s, 1, 1); } -fail: - if (seg->list) - ff_format_io_close(s, &seg->list_pb); - - av_opt_free(seg); - av_freep(&seg->cur_entry.filename); - - cur = seg->segment_list_entries; - while (cur) { - next = cur->next; - av_freep(&cur->filename); - av_free(cur); - cur = next; - } - - avformat_free_context(oc); - seg->avf = NULL; return ret; } @@ -1069,7 +1053,7 @@ static const AVClass seg_class = { .version = LIBAVUTIL_VERSION_INT, }; -AVOutputFormat ff_segment_muxer = { +const AVOutputFormat ff_segment_muxer = { .name = "segment", .long_name = NULL_IF_CONFIG_SMALL("segment"), .priv_data_size = sizeof(SegmentContext), @@ -1092,7 +1076,7 @@ static const AVClass sseg_class = { .version = LIBAVUTIL_VERSION_INT, }; -AVOutputFormat ff_stream_segment_muxer = { +const AVOutputFormat ff_stream_segment_muxer = { .name = "stream_segment,ssegment", .long_name = NULL_IF_CONFIG_SMALL("streaming segment muxer"), .priv_data_size = sizeof(SegmentContext),