[FFmpeg-devel] [PATCH v1 1/1] Matroid patch: add support for writing additional metadata to filename
* Support micro seconds for image2 strftime filename * Support micro seconds for segment strftime filename * Support duration for segment output * Allow split on keyframe with NOPTS * Add EXT-X-PROGRAM-DATE-TIME parsing to hls.c * Add global timestamp (gts) metatdata to AVPacket and AVFrame * Support gts for image2 filename * Support gts for segment filename Signed-off-by: tak-matroid --- fftools/ffmpeg.c | 1 + libavcodec/avpacket.c | 2 + libavcodec/decode.c | 1 + libavcodec/encode.c | 9 +++ libavcodec/packet.h | 2 + libavformat/avformat.h| 5 +- libavformat/hls.c | 56 ++ libavformat/hlsenc.c | 15 +++-- libavformat/img2enc.c | 49 libavformat/segment.c | 119 +- libavformat/utils.c | 49 +++- libavutil/Makefile| 1 - libavutil/frame.c | 2 + libavutil/frame.h | 2 + libavutil/time.c | 17 ++ libavutil/time.h | 11 libavutil/time_internal.h | 23 17 files changed, 314 insertions(+), 50 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index add5a3e505..9f3ea8a691 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2117,6 +2117,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } else opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); opkt.dts -= ost_tb_start_time; +opkt.gts = pkt->gts; opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index e4ba403cf6..08eb0dc5cb 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -37,6 +37,7 @@ void av_init_packet(AVPacket *pkt) pkt->pts = AV_NOPTS_VALUE; pkt->dts = AV_NOPTS_VALUE; pkt->pos = -1; +pkt->gts = -1; pkt->duration = 0; #if FF_API_CONVERGENCE_DURATION FF_DISABLE_DEPRECATION_WARNINGS @@ -575,6 +576,7 @@ int av_packet_copy_props(AVPacket *dst, const AVPacket *src) dst->pts = src->pts; dst->dts = src->dts; +dst->gts = src->gts; dst->pos = src->pos; dst->duration = src->duration; #if FF_API_CONVERGENCE_DURATION diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 8086362eb2..499ec4bd85 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1741,6 +1741,7 @@ FF_ENABLE_DEPRECATION_WARNINGS frame->pkt_pos = pkt->pos; frame->pkt_duration = pkt->duration; frame->pkt_size = pkt->size; +frame->gts = pkt->gts; for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) { int size; diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 282337e453..b5a6dde879 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -126,6 +126,7 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) AVFrame *frame = es->in_frame; int got_packet; int ret; +double gts = -1; if (avci->draining_done) return AVERROR_EOF; @@ -137,6 +138,10 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) return ret; } +// record frame global timestamp +if (frame) +gts = frame->gts; + if (!frame->buf[0]) { if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY || (avci->frame_thread_encoder && avctx->active_thread_type & FF_THREAD_FRAME))) @@ -164,6 +169,10 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) avpkt->pts = avpkt->dts = frame->pts; } +// assign global timestamp if available +if (gts > 0 && avpkt->gts <= 0) +avpkt->gts = gts; + av_assert0(ret <= 0); emms_c(); diff --git a/libavcodec/packet.h b/libavcodec/packet.h index b9d4c9c2c8..8b4fee759b 100644 --- a/libavcodec/packet.h +++ b/libavcodec/packet.h @@ -391,6 +391,8 @@ typedef struct AVPacket { attribute_deprecated int64_t convergence_duration; #endif + +double gts; } AVPacket; typedef struct AVPacketList { diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 41482328f6..38c90cba26 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2803,8 +2803,11 @@ void av_dump_format(AVFormatContext *ic, * @param flags AV_FRAME_FILENAME_FLAGS_* * @return 0 if OK, -1 on format error */ +int av_get_frame_filename3(char *buf, int buf_size, + const char *path, int number, int flags, int64_t ts, double duration, double global_timestamp); + int av_get
[FFmpeg-devel] [PATCH] Matroid patch: add support for writing additional metadata to filename
* Support micro seconds for image2 strftime filename * Support micro seconds for segment strftime filename * Support duration for segment output Signed-off-by: tak-matroid --- libavformat/avformat.h | 7 - libavformat/img2enc.c | 40 +-- libavformat/segment.c | 61 +- libavformat/utils.c| 38 +++--- libavutil/time.c | 17 libavutil/time.h | 11 6 files changed, 149 insertions(+), 25 deletions(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 7da2f3d98e..f5084f622c 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2808,10 +2808,15 @@ void av_dump_format(AVFormatContext *ic, * @param path numbered sequence string * @param number frame number * @param flags AV_FRAME_FILENAME_FLAGS_* + * @param ts frame pts in AV_TIME_BASE_Q + * @param duration duration of segment * @return 0 if OK, -1 on format error */ +int av_get_frame_filename3(char *buf, int buf_size, + const char *path, int number, int flags, int64_t ts, double duration); + int av_get_frame_filename2(char *buf, int buf_size, - const char *path, int number, int flags); + const char *path, int number, int flags, int64_t ts); int av_get_frame_filename(char *buf, int buf_size, const char *path, int number); diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 0f7a21ffa0..37118d02fc 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -27,7 +27,9 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/time.h" #include "libavutil/time_internal.h" +#include #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -130,31 +132,40 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) VideoMuxData *img = s->priv_data; AVIOContext *pb[4] = {0}; char filename[1024]; -AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; +AVStream *stream = s->streams[pkt->stream_index]; +AVCodecParameters *par = stream->codecpar; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format); int ret, i; int nb_renames = 0; +int64_t ts = av_rescale_q(pkt->pts, stream->time_base, AV_TIME_BASE_Q); AVDictionary *options = NULL; if (img->update) { av_strlcpy(filename, img->path, sizeof(filename)); -} else if (img->use_strftime) { -time_t now0; -struct tm *tm, tmpbuf; -time(&now0); -tm = localtime_r(&now0, &tmpbuf); -if (!strftime(filename, sizeof(filename), img->path, tm)) { -av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); -return AVERROR(EINVAL); +} else if (img->use_strftime || img->frame_pts) { +char temp_name[sizeof(filename)]; +if (img->use_strftime) { +struct timeval tv; +gettimeofday(&tv, NULL); +if (!av_strftime_micro(temp_name, sizeof(temp_name), img->path, &tv)) { +av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); +return AVERROR(EINVAL); +} +} else { +av_strlcpy(temp_name, img->path, sizeof(temp_name)); } -} else if (img->frame_pts) { -if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { -av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); -return AVERROR(EINVAL); + +if (img->frame_pts) { +if (av_get_frame_filename2(filename, sizeof(filename), temp_name, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0) { +av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); +return AVERROR(EINVAL); +} +} else { +av_strlcpy(filename, temp_name, sizeof(filename)); } } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, img->img_number, - AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0 && + AV_FRAME_FILENAME_FLAGS_MULTIPLE, ts) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s'. " @@ -162,6 +173,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) img->img_number, img->path); return AVERROR(EINVAL);