summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2023-04-24 16:47:50 +0200
committerAnton Khirnov <anton@khirnov.net>2023-05-02 10:57:21 +0200
commit0ed1eeb74435c6d10edd251ce3529fce8ea564d6 (patch)
tree86bf6f3dc9fee4970ac3e317ee893f51cf31f9b1 /libavformat
parentaae5ba31ca94307c15e134d98e7492cf5a208426 (diff)
downloadffmpeg-0ed1eeb74435c6d10edd251ce3529fce8ea564d6.tar.gz
lavf/dv: use a more granular timebase for audio
One that is fine enough to represent all DV audio sample rates. Audio packet durations are now sample-accurate. This largely undoes commit 76fbb0052df471075858c1cb82b04c8be7adba8d. To avoid breaking the issue fixed by that commit, resync audio timestamps against video if they get more than one frame apart. The sample from issue #8762 still works correctly after this commit. Slightly changes the results of the lavf-dv seektest, due to the audio timebase being more granular.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/dv.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/libavformat/dv.c b/libavformat/dv.c
index 227caf168f..d01ecedc62 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -71,6 +71,7 @@ struct DVDemuxContext {
int frames;
int64_t next_pts_video;
+ int64_t next_pts_audio;
};
static inline uint16_t dv_audio_12to16(uint16_t sample)
@@ -282,7 +283,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
if (!c->ast[i])
return AVERROR(ENOMEM);
- avpriv_set_pts_info(c->ast[i], 64, c->sys->time_base.num, c->sys->time_base.den);
+ avpriv_set_pts_info(c->ast[i], 64, 1, DV_TIMESCALE_AUDIO);
c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
c->ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
c->ast[i]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
@@ -421,6 +422,7 @@ int avpriv_dv_get_packet(DVDemuxContext *c, AVPacket *pkt)
int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
uint8_t *buf, int buf_size, int64_t pos)
{
+ int64_t pts, duration;
int size, i;
uint8_t *ppcm[5] = { 0 };
@@ -436,13 +438,30 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
if (size < 0)
return size;
+ if (c->ach) {
+ int64_t next_pts_video = av_rescale_q(c->next_pts_video, c->vst->time_base,
+ c->ast[0]->time_base);
+
+ duration = av_rescale_q(size / 4,
+ (AVRational){ 1, c->audio_pkt[0].sample_rate },
+ c->ast[0]->time_base);
+
+ // if audio timestamps are more than one frame away from video,
+ // assume desync happened (e.g. due to dropped audio frames) and
+ // resynchronize
+ pts = (FFABS(next_pts_video - c->next_pts_audio) >= duration) ?
+ next_pts_video : c->next_pts_audio;
+
+ c->next_pts_audio = pts + duration;
+ }
+
for (i = 0; i < c->ach; i++) {
DVPacket *dpkt = &c->audio_pkt[i];
dpkt->pos = pos;
dpkt->size = size;
- dpkt->pts = (c->sys->height == 720) ? (c->frames & ~1) : c->frames;
- dpkt->duration = 1;
+ dpkt->pts = pts;
+ dpkt->duration = duration;
ppcm[i] = c->audio_buf[i];
}
@@ -507,6 +526,8 @@ void ff_dv_ts_reset(DVDemuxContext *c, int64_t ts)
c->frames = !c->sys ? 0 :
av_rescale_q(ts, c->vst->time_base, c->sys->time_base);
c->next_pts_video = ts;
+ c->next_pts_audio = (!c->sys || !c->ast[0]) ? AV_NOPTS_VALUE :
+ av_rescale_q(ts, c->vst->time_base, c->ast[0]->time_base);
c->audio_pkt[0].size = c->audio_pkt[1].size = 0;
c->audio_pkt[2].size = c->audio_pkt[3].size = 0;