mirror of
				https://github.com/nyanmisaka/ffmpeg-rockchip.git
				synced 2025-10-31 20:42:49 +08:00 
			
		
		
		
	lavf/segment: add SegmentListEntry and use it
This patch is propedeutic to the incoming patch which adds support to sliding window segment listing.
This commit is contained in:
		| @@ -31,6 +31,7 @@ | |||||||
| #include "avformat.h" | #include "avformat.h" | ||||||
| #include "internal.h" | #include "internal.h" | ||||||
|  |  | ||||||
|  | #include "libavutil/avassert.h" | ||||||
| #include "libavutil/log.h" | #include "libavutil/log.h" | ||||||
| #include "libavutil/opt.h" | #include "libavutil/opt.h" | ||||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||||
| @@ -38,6 +39,14 @@ | |||||||
| #include "libavutil/mathematics.h" | #include "libavutil/mathematics.h" | ||||||
| #include "libavutil/timestamp.h" | #include "libavutil/timestamp.h" | ||||||
|  |  | ||||||
|  | typedef struct SegmentListEntry { | ||||||
|  |     int index; | ||||||
|  |     double start_time, end_time; | ||||||
|  |     int64_t start_pts, start_dts; | ||||||
|  |     char filename[1024]; | ||||||
|  |     struct SegmentListEntry *next; | ||||||
|  | } SegmentListEntry; | ||||||
|  |  | ||||||
| typedef enum { | typedef enum { | ||||||
|     LIST_TYPE_UNDEFINED = -1, |     LIST_TYPE_UNDEFINED = -1, | ||||||
|     LIST_TYPE_FLAT = 0, |     LIST_TYPE_FLAT = 0, | ||||||
| @@ -85,8 +94,7 @@ typedef struct { | |||||||
|     char *reference_stream_specifier; ///< reference stream specifier |     char *reference_stream_specifier; ///< reference stream specifier | ||||||
|     int   reference_stream_index; |     int   reference_stream_index; | ||||||
|  |  | ||||||
|     double start_time, end_time; |     SegmentListEntry cur_entry; | ||||||
|     int64_t start_pts, start_dts; |  | ||||||
|     int is_first_pkt;      ///< tells if it is the first packet in the segment |     int is_first_pkt;      ///< tells if it is the first packet in the segment | ||||||
| } SegmentContext; | } SegmentContext; | ||||||
|  |  | ||||||
| @@ -153,6 +161,7 @@ static int set_segment_filename(AVFormatContext *s) | |||||||
|         av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->filename); |         av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->filename); | ||||||
|         return AVERROR(EINVAL); |         return AVERROR(EINVAL); | ||||||
|     } |     } | ||||||
|  |     av_strlcpy(seg->cur_entry.filename, oc->filename, sizeof(seg->cur_entry.filename)); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -230,6 +239,28 @@ static void segment_list_close(AVFormatContext *s) | |||||||
|     avio_close(seg->list_pb); |     avio_close(seg->list_pb); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void segment_list_print_entry(AVIOContext      *list_ioctx, | ||||||
|  |                                      ListType          list_type, | ||||||
|  |                                      const SegmentListEntry *list_entry) | ||||||
|  | { | ||||||
|  |     switch (list_type) { | ||||||
|  |     case LIST_TYPE_FLAT: | ||||||
|  |         avio_printf(list_ioctx, "%s\n", list_entry->filename); | ||||||
|  |         break; | ||||||
|  |     case LIST_TYPE_CSV: | ||||||
|  |     case LIST_TYPE_EXT: | ||||||
|  |         print_csv_escaped_str(list_ioctx, list_entry->filename); | ||||||
|  |         avio_printf(list_ioctx, ",%f,%f\n", list_entry->start_time, list_entry->end_time); | ||||||
|  |         break; | ||||||
|  |     case LIST_TYPE_M3U8: | ||||||
|  |         avio_printf(list_ioctx, "#EXTINF:%f,\n%s\n", | ||||||
|  |                     list_entry->end_time - list_entry->start_time, list_entry->filename); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         av_assert0(!"Invalid list type"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static int segment_end(AVFormatContext *s, int write_trailer) | static int segment_end(AVFormatContext *s, int write_trailer) | ||||||
| { | { | ||||||
|     SegmentContext *seg = s->priv_data; |     SegmentContext *seg = s->priv_data; | ||||||
| @@ -251,16 +282,9 @@ static int segment_end(AVFormatContext *s, int write_trailer) | |||||||
|                 goto end; |                 goto end; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (seg->list_type == LIST_TYPE_FLAT) { |         segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry); | ||||||
|             avio_printf(seg->list_pb, "%s\n", oc->filename); |         seg->list_max_segment_time = | ||||||
|         } else if (seg->list_type == LIST_TYPE_CSV || seg->list_type == LIST_TYPE_EXT) { |             FFMAX(seg->cur_entry.end_time - seg->cur_entry.start_time, seg->list_max_segment_time); | ||||||
|             print_csv_escaped_str(seg->list_pb, oc->filename); |  | ||||||
|             avio_printf(seg->list_pb, ",%f,%f\n", seg->start_time, seg->end_time); |  | ||||||
|         } else if (seg->list_type == LIST_TYPE_M3U8) { |  | ||||||
|             avio_printf(seg->list_pb, "#EXTINF:%f,\n%s\n", |  | ||||||
|                         seg->end_time - seg->start_time, oc->filename); |  | ||||||
|         } |  | ||||||
|         seg->list_max_segment_time = FFMAX(seg->end_time - seg->start_time, seg->list_max_segment_time); |  | ||||||
|         avio_flush(seg->list_pb); |         avio_flush(seg->list_pb); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -619,13 +643,14 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) | |||||||
|  |  | ||||||
|         oc = seg->avf; |         oc = seg->avf; | ||||||
|  |  | ||||||
|         seg->start_time = (double)pkt->pts * av_q2d(st->time_base); |         seg->cur_entry.index = seg->segment_idx; | ||||||
|         seg->start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); |         seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base); | ||||||
|         seg->start_dts = pkt->dts != AV_NOPTS_VALUE ? |         seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); | ||||||
|             av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q) : seg->start_pts; |         seg->cur_entry.start_dts = pkt->dts != AV_NOPTS_VALUE ? | ||||||
|  |             av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q) : seg->cur_entry.start_pts; | ||||||
|     } else if (pkt->pts != AV_NOPTS_VALUE) { |     } else if (pkt->pts != AV_NOPTS_VALUE) { | ||||||
|         seg->end_time = FFMAX(seg->end_time, |         seg->cur_entry.end_time = | ||||||
|                               (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base)); |             FFMAX(seg->cur_entry.end_time, (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (seg->is_first_pkt) { |     if (seg->is_first_pkt) { | ||||||
| @@ -637,14 +662,14 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) | |||||||
|  |  | ||||||
|     if (seg->reset_timestamps) { |     if (seg->reset_timestamps) { | ||||||
|         av_log(s, AV_LOG_DEBUG, "start_pts:%s pts:%s start_dts:%s dts:%s", |         av_log(s, AV_LOG_DEBUG, "start_pts:%s pts:%s start_dts:%s dts:%s", | ||||||
|                av_ts2timestr(seg->start_pts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->pts, &st->time_base), |                av_ts2timestr(seg->cur_entry.start_pts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->pts, &st->time_base), | ||||||
|                av_ts2timestr(seg->start_dts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->dts, &st->time_base)); |                av_ts2timestr(seg->cur_entry.start_dts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->dts, &st->time_base)); | ||||||
|  |  | ||||||
|         /* compute new timestamps */ |         /* compute new timestamps */ | ||||||
|         if (pkt->pts != AV_NOPTS_VALUE) |         if (pkt->pts != AV_NOPTS_VALUE) | ||||||
|             pkt->pts -= av_rescale_q(seg->start_pts, AV_TIME_BASE_Q, st->time_base); |             pkt->pts -= av_rescale_q(seg->cur_entry.start_pts, AV_TIME_BASE_Q, st->time_base); | ||||||
|         if (pkt->dts != AV_NOPTS_VALUE) |         if (pkt->dts != AV_NOPTS_VALUE) | ||||||
|             pkt->dts -= av_rescale_q(seg->start_dts, AV_TIME_BASE_Q, st->time_base); |             pkt->dts -= av_rescale_q(seg->cur_entry.start_dts, AV_TIME_BASE_Q, st->time_base); | ||||||
|  |  | ||||||
|         av_log(s, AV_LOG_DEBUG, " -> pts:%s dts:%s\n", |         av_log(s, AV_LOG_DEBUG, " -> pts:%s dts:%s\n", | ||||||
|                av_ts2timestr(pkt->pts, &st->time_base), av_ts2timestr(pkt->dts, &st->time_base)); |                av_ts2timestr(pkt->pts, &st->time_base), av_ts2timestr(pkt->dts, &st->time_base)); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stefano Sabatini
					Stefano Sabatini