[FFmpeg-devel] [PATCH v1 1/1] Matroid patch: add support for writing additional metadata to filename

2021-02-22 Thread tak-matroid
* 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

2021-03-09 Thread tak-matroid
* 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);