* [FFmpeg-devel] [PATCH 1/3] fftools/ffmpeg: merge DemuxPktData into FrameData
@ 2023-12-12 12:09 Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 2/3] fftools/ffmpeg: attach wallclock timing information to packets and frames Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg_mux: print latency information in -debug_ts muxing output Anton Khirnov
0 siblings, 2 replies; 3+ messages in thread
From: Anton Khirnov @ 2023-12-12 12:09 UTC (permalink / raw)
To: ffmpeg-devel
This way we can propagate arbitrary data from the demuxer all the way
into the muxer, using a single struct.
---
fftools/ffmpeg.c | 28 ++++++++++++++++++++--------
fftools/ffmpeg.h | 13 +++++++------
fftools/ffmpeg_demux.c | 9 ++++-----
fftools/ffmpeg_mux.c | 4 ++--
4 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 30b594fd97..e7ff9a6d6f 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -404,36 +404,48 @@ InputStream *ist_iter(InputStream *prev)
return NULL;
}
-static int frame_data_ensure(AVFrame *frame, int writable)
+static int frame_data_ensure(AVBufferRef **dst, int writable)
{
- if (!frame->opaque_ref) {
+ if (!*dst) {
FrameData *fd;
- frame->opaque_ref = av_buffer_allocz(sizeof(*fd));
- if (!frame->opaque_ref)
+ *dst = av_buffer_allocz(sizeof(*fd));
+ if (!*dst)
return AVERROR(ENOMEM);
- fd = (FrameData*)frame->opaque_ref->data;
+ fd = (FrameData*)((*dst)->data);
fd->dec.frame_num = UINT64_MAX;
fd->dec.pts = AV_NOPTS_VALUE;
} else if (writable)
- return av_buffer_make_writable(&frame->opaque_ref);
+ return av_buffer_make_writable(dst);
return 0;
}
FrameData *frame_data(AVFrame *frame)
{
- int ret = frame_data_ensure(frame, 1);
+ int ret = frame_data_ensure(&frame->opaque_ref, 1);
return ret < 0 ? NULL : (FrameData*)frame->opaque_ref->data;
}
const FrameData *frame_data_c(AVFrame *frame)
{
- int ret = frame_data_ensure(frame, 0);
+ int ret = frame_data_ensure(&frame->opaque_ref, 0);
return ret < 0 ? NULL : (const FrameData*)frame->opaque_ref->data;
}
+FrameData *packet_data(AVPacket *pkt)
+{
+ int ret = frame_data_ensure(&pkt->opaque_ref, 1);
+ return ret < 0 ? NULL : (FrameData*)pkt->opaque_ref->data;
+}
+
+const FrameData *packet_data_c(AVPacket *pkt)
+{
+ int ret = frame_data_ensure(&pkt->opaque_ref, 0);
+ return ret < 0 ? NULL : (const FrameData*)pkt->opaque_ref->data;
+}
+
void remove_avoptions(AVDictionary **a, AVDictionary *b)
{
const AVDictionaryEntry *t = NULL;
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index ba82b7490d..aafb35538e 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -115,12 +115,6 @@ typedef struct {
} AudioChannelMap;
#endif
-typedef struct DemuxPktData {
- // estimated dts in AV_TIME_BASE_Q,
- // to be used when real dts is missing
- int64_t dts_est;
-} DemuxPktData;
-
typedef struct OptionsContext {
OptionGroup *g;
@@ -622,6 +616,10 @@ typedef struct OutputFile {
// optionally attached as opaque_ref to decoded AVFrames
typedef struct FrameData {
+ // demuxer-estimated dts in AV_TIME_BASE_Q,
+ // to be used when real dts is missing
+ int64_t dts_est;
+
// properties that come from the decoder
struct {
uint64_t frame_num;
@@ -723,6 +721,9 @@ FrameData *frame_data(AVFrame *frame);
const FrameData *frame_data_c(AVFrame *frame);
+FrameData *packet_data (AVPacket *pkt);
+const FrameData *packet_data_c(AVPacket *pkt);
+
/**
* Set up fallback filtering parameters from a decoder context. They will only
* be used if no frames are ever sent on this input, otherwise the actual
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 91cd7a1125..392b447338 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -328,14 +328,13 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt)
av_assert0(!pkt->opaque_ref);
if (ds->streamcopy_needed) {
- DemuxPktData *pd;
+ FrameData *fd;
- pkt->opaque_ref = av_buffer_allocz(sizeof(*pd));
- if (!pkt->opaque_ref)
+ fd = packet_data(pkt);
+ if (!fd)
return AVERROR(ENOMEM);
- pd = (DemuxPktData*)pkt->opaque_ref->data;
- pd->dts_est = ds->dts;
+ fd->dts_est = ds->dts;
}
return 0;
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 067dc65d4e..62925be8d0 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -381,8 +381,8 @@ static int of_streamcopy(OutputStream *ost, AVPacket *pkt)
{
OutputFile *of = output_files[ost->file_index];
MuxStream *ms = ms_from_ost(ost);
- DemuxPktData *pd = pkt->opaque_ref ? (DemuxPktData*)pkt->opaque_ref->data : NULL;
- int64_t dts = pd ? pd->dts_est : AV_NOPTS_VALUE;
+ FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL;
+ int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE;
int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time;
int64_t ts_offset;
--
2.42.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* [FFmpeg-devel] [PATCH 2/3] fftools/ffmpeg: attach wallclock timing information to packets and frames
2023-12-12 12:09 [FFmpeg-devel] [PATCH 1/3] fftools/ffmpeg: merge DemuxPktData into FrameData Anton Khirnov
@ 2023-12-12 12:09 ` Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg_mux: print latency information in -debug_ts muxing output Anton Khirnov
1 sibling, 0 replies; 3+ messages in thread
From: Anton Khirnov @ 2023-12-12 12:09 UTC (permalink / raw)
To: ffmpeg-devel
Will become useful in following commits.
---
fftools/ffmpeg.c | 3 +++
fftools/ffmpeg.h | 13 +++++++++++++
fftools/ffmpeg_dec.c | 14 ++++++++++++--
fftools/ffmpeg_demux.c | 26 ++++++++++++--------------
fftools/ffmpeg_enc.c | 16 ++++++++++++++++
fftools/ffmpeg_filter.c | 9 +++++++++
6 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index e7ff9a6d6f..42e675dcb9 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -416,6 +416,9 @@ static int frame_data_ensure(AVBufferRef **dst, int writable)
fd->dec.frame_num = UINT64_MAX;
fd->dec.pts = AV_NOPTS_VALUE;
+
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i++)
+ fd->wallclock[i] = INT64_MIN;
} else if (writable)
return av_buffer_make_writable(dst);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index aafb35538e..7f84f3266d 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -94,6 +94,17 @@ enum PacketOpaque {
PKT_OPAQUE_FIX_SUB_DURATION,
};
+enum LatencyProbe {
+ LATENCY_PROBE_DEMUX,
+ LATENCY_PROBE_DEC_PRE,
+ LATENCY_PROBE_DEC_POST,
+ LATENCY_PROBE_FILTER_PRE,
+ LATENCY_PROBE_FILTER_POST,
+ LATENCY_PROBE_ENC_PRE,
+ LATENCY_PROBE_ENC_POST,
+ LATENCY_PROBE_NB,
+};
+
typedef struct HWDevice {
const char *name;
enum AVHWDeviceType type;
@@ -631,6 +642,8 @@ typedef struct FrameData {
AVRational frame_rate_filter;
int bits_per_raw_sample;
+
+ int64_t wallclock[LATENCY_PROBE_NB];
} FrameData;
extern InputFile **input_files;
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index 5dde82a276..ce5aa33f73 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -22,6 +22,7 @@
#include "libavutil/log.h"
#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
+#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavcodec/avcodec.h"
@@ -475,6 +476,13 @@ static int packet_decode(InputStream *ist, AVPacket *pkt, AVFrame *frame)
pkt->dts = AV_NOPTS_VALUE;
}
+ if (pkt) {
+ FrameData *fd = packet_data(pkt);
+ if (!fd)
+ return AVERROR(ENOMEM);
+ fd->wallclock[LATENCY_PROBE_DEC_PRE] = av_gettime_relative();
+ }
+
ret = avcodec_send_packet(dec, pkt);
if (ret < 0 && !(ret == AVERROR_EOF && !pkt)) {
// In particular, we don't expect AVERROR(EAGAIN), because we read all
@@ -528,8 +536,6 @@ static int packet_decode(InputStream *ist, AVPacket *pkt, AVFrame *frame)
return AVERROR_INVALIDDATA;
}
-
- av_assert0(!frame->opaque_ref);
fd = frame_data(frame);
if (!fd) {
av_frame_unref(frame);
@@ -540,6 +546,8 @@ static int packet_decode(InputStream *ist, AVPacket *pkt, AVFrame *frame)
fd->dec.frame_num = dec->frame_num - 1;
fd->bits_per_raw_sample = dec->bits_per_raw_sample;
+ fd->wallclock[LATENCY_PROBE_DEC_POST] = av_gettime_relative();
+
frame->time_base = dec->pkt_timebase;
if (dec->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -932,6 +940,8 @@ int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx)
if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
av_dict_set(&ist->decoder_opts, "threads", "1", 0);
+ av_dict_set(&ist->decoder_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY);
+
ret = hw_device_setup_for_decode(ist);
if (ret < 0) {
av_log(ist, AV_LOG_ERROR,
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index 392b447338..d2466e885d 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -271,7 +271,7 @@ static void ts_discontinuity_process(Demuxer *d, InputStream *ist,
ts_discontinuity_detect(d, ist, pkt);
}
-static int ist_dts_update(DemuxStream *ds, AVPacket *pkt)
+static int ist_dts_update(DemuxStream *ds, AVPacket *pkt, FrameData *fd)
{
InputStream *ist = &ds->ist;
const AVCodecParameters *par = ist->par;
@@ -326,21 +326,12 @@ static int ist_dts_update(DemuxStream *ds, AVPacket *pkt)
break;
}
- av_assert0(!pkt->opaque_ref);
- if (ds->streamcopy_needed) {
- FrameData *fd;
-
- fd = packet_data(pkt);
- if (!fd)
- return AVERROR(ENOMEM);
-
- fd->dts_est = ds->dts;
- }
+ fd->dts_est = ds->dts;
return 0;
}
-static int ts_fixup(Demuxer *d, AVPacket *pkt)
+static int ts_fixup(Demuxer *d, AVPacket *pkt, FrameData *fd)
{
InputFile *ifile = &d->f;
InputStream *ist = ifile->streams[pkt->stream_index];
@@ -424,7 +415,7 @@ static int ts_fixup(Demuxer *d, AVPacket *pkt)
ts_discontinuity_process(d, ist, pkt);
// update estimated/predicted dts
- ret = ist_dts_update(ds, pkt);
+ ret = ist_dts_update(ds, pkt, fd);
if (ret < 0)
return ret;
@@ -436,9 +427,14 @@ static int input_packet_process(Demuxer *d, AVPacket *pkt, unsigned *send_flags)
InputFile *f = &d->f;
InputStream *ist = f->streams[pkt->stream_index];
DemuxStream *ds = ds_from_ist(ist);
+ FrameData *fd;
int ret = 0;
- ret = ts_fixup(d, pkt);
+ fd = packet_data(pkt);
+ if (!fd)
+ return AVERROR(ENOMEM);
+
+ ret = ts_fixup(d, pkt, fd);
if (ret < 0)
return ret;
@@ -455,6 +451,8 @@ static int input_packet_process(Demuxer *d, AVPacket *pkt, unsigned *send_flags)
ds->data_size += pkt->size;
ds->nb_packets++;
+ fd->wallclock[LATENCY_PROBE_DEMUX] = av_gettime_relative();
+
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n",
f->index, pkt->stream_index,
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index 320df2dee7..43e8b077eb 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -34,6 +34,7 @@
#include "libavutil/log.h"
#include "libavutil/pixdesc.h"
#include "libavutil/rational.h"
+#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavcodec/avcodec.h"
@@ -615,6 +616,14 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
int ret;
if (frame) {
+ FrameData *fd = frame_data(frame);
+
+ fd = frame_data(frame);
+ if (!fd)
+ return AVERROR(ENOMEM);
+
+ fd->wallclock[LATENCY_PROBE_ENC_PRE] = av_gettime_relative();
+
if (ost->enc_stats_pre.io)
enc_stats_write(ost, &ost->enc_stats_pre, frame, NULL,
ost->frames_encoded);
@@ -644,6 +653,8 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
}
while (1) {
+ FrameData *fd;
+
av_packet_unref(pkt);
ret = avcodec_receive_packet(enc, pkt);
@@ -665,6 +676,11 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
return ret;
}
+ fd = packet_data(pkt);
+ if (!fd)
+ return AVERROR(ENOMEM);
+ fd->wallclock[LATENCY_PROBE_ENC_POST] = av_gettime_relative();
+
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
ret = update_video_stats(ost, pkt, !!vstats_filename);
if (ret < 0)
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index ada235b084..21f823be12 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -36,6 +36,7 @@
#include "libavutil/pixfmt.h"
#include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h"
+#include "libavutil/time.h"
#include "libavutil/timestamp.h"
// FIXME private header, used for mid_pred()
@@ -2364,6 +2365,8 @@ static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
return AVERROR(ENOMEM);
}
+ fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
+
// only use bits_per_raw_sample passed through from the decoder
// if the filtergraph did not touch the frame data
if (!fgp->is_meta)
@@ -2576,6 +2579,7 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
InputFilter *ifilter, AVFrame *frame)
{
InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
+ FrameData *fd;
AVFrameSideData *sd;
int need_reinit, ret;
@@ -2651,6 +2655,11 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
)
#endif
+ fd = frame_data(frame);
+ if (!fd)
+ return AVERROR(ENOMEM);
+ fd->wallclock[LATENCY_PROBE_FILTER_PRE] = av_gettime_relative();
+
ret = av_buffersrc_add_frame_flags(ifp->filter, frame,
AV_BUFFERSRC_FLAG_PUSH);
if (ret < 0) {
--
2.42.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
* [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg_mux: print latency information in -debug_ts muxing output
2023-12-12 12:09 [FFmpeg-devel] [PATCH 1/3] fftools/ffmpeg: merge DemuxPktData into FrameData Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 2/3] fftools/ffmpeg: attach wallclock timing information to packets and frames Anton Khirnov
@ 2023-12-12 12:09 ` Anton Khirnov
1 sibling, 0 replies; 3+ messages in thread
From: Anton Khirnov @ 2023-12-12 12:09 UTC (permalink / raw)
To: ffmpeg-devel
---
fftools/ffmpeg_mux.c | 87 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c
index 62925be8d0..ca1996622d 100644
--- a/fftools/ffmpeg_mux.c
+++ b/fftools/ffmpeg_mux.c
@@ -25,10 +25,12 @@
#include "ffmpeg_utils.h"
#include "sync_queue.h"
+#include "libavutil/avstring.h"
#include "libavutil/fifo.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
+#include "libavutil/time.h"
#include "libavutil/timestamp.h"
#include "libavcodec/packet.h"
@@ -59,6 +61,79 @@ static int64_t filesize(AVIOContext *pb)
return ret;
}
+static void mux_log_debug_ts(OutputStream *ost, const AVPacket *pkt)
+{
+ static const char *desc[] = {
+ [LATENCY_PROBE_DEMUX] = "demux",
+ [LATENCY_PROBE_DEC_PRE] = "decode",
+ [LATENCY_PROBE_DEC_POST] = "decode",
+ [LATENCY_PROBE_FILTER_PRE] = "filter",
+ [LATENCY_PROBE_FILTER_POST] = "filter",
+ [LATENCY_PROBE_ENC_PRE] = "encode",
+ [LATENCY_PROBE_ENC_POST] = "encode",
+ [LATENCY_PROBE_NB] = "mux",
+ };
+
+ char latency[512] = { 0 };
+
+ if (pkt->opaque_ref) {
+ const FrameData *fd = (FrameData*)pkt->opaque_ref->data;
+ int64_t now = av_gettime_relative();
+ int64_t total = INT64_MIN;
+
+ int next;
+
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i = next) {
+ int64_t val = fd->wallclock[i];
+
+ next = i + 1;
+
+ if (val == INT64_MIN)
+ continue;
+
+ if (total == INT64_MIN) {
+ total = now - val;
+ snprintf(latency, sizeof(latency), "total:%gms", total / 1e3);
+ }
+
+ // find the next valid entry
+ for (; next <= FF_ARRAY_ELEMS(fd->wallclock); next++) {
+ int64_t val_next = (next == FF_ARRAY_ELEMS(fd->wallclock)) ?
+ now : fd->wallclock[next];
+ int64_t diff;
+
+ if (val_next == INT64_MIN)
+ continue;
+ diff = val_next - val;
+
+ // print those stages that take at least 5% of total
+ if (100. * diff > 5. * total) {
+ av_strlcat(latency, ", ", sizeof(latency));
+
+ if (!strcmp(desc[i], desc[next]))
+ av_strlcat(latency, desc[i], sizeof(latency));
+ else
+ av_strlcatf(latency, sizeof(latency), "%s-%s:",
+ desc[i], desc[next]);
+
+ av_strlcatf(latency, sizeof(latency), " %gms/%d%%",
+ diff / 1e3, (int)(100. * diff / total));
+ }
+
+ break;
+ }
+
+ }
+ }
+
+ av_log(ost, AV_LOG_INFO, "muxer <- pts:%s pts_time:%s dts:%s dts_time:%s "
+ "duration:%s duration_time:%s size:%d latency(%s)\n",
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
+ pkt->size, *latency ? latency : "N/A");
+}
+
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
{
MuxStream *ms = ms_from_ost(ost);
@@ -140,16 +215,8 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
pkt->stream_index = ost->index;
- if (debug_ts) {
- av_log(ost, AV_LOG_INFO, "muxer <- type:%s "
- "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n",
- av_get_media_type_string(ost->type),
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base),
- pkt->size
- );
- }
+ if (debug_ts)
+ mux_log_debug_ts(ost, pkt);
if (ms->stats.io)
enc_stats_write(ost, &ms->stats, NULL, pkt, frame_num);
--
2.42.0
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-12-12 12:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-12 12:09 [FFmpeg-devel] [PATCH 1/3] fftools/ffmpeg: merge DemuxPktData into FrameData Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 2/3] fftools/ffmpeg: attach wallclock timing information to packets and frames Anton Khirnov
2023-12-12 12:09 ` [FFmpeg-devel] [PATCH 3/3] fftools/ffmpeg_mux: print latency information in -debug_ts muxing output Anton Khirnov
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git