aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2024-03-02 22:56:35 +0100
committerMarton Balint <cus@passwd.hu>2024-03-16 19:19:42 +0100
commit9c2c0c37f8c775d2bdca1730789fbdae75922acd (patch)
treea1d7b794cbabe9387cd4b93988ad0eaaad8c62d0 /libavformat
parentf5441e441f9b0d235e49bdccc69e141ccd92e854 (diff)
downloadffmpeg-9c2c0c37f8c775d2bdca1730789fbdae75922acd.tar.gz
avformat/pcm: factorize and improve determining the default packet size
- Remove the 1024 cap on the number of samples, for high sample rate audio it was suboptimal, calculate the low neighbour power of two for the number of samples (audio blocks) instead. - Make the function work correctly also for non-pcm codecs by using the stream bitrate to estimate the target packet size. A previous version of this patch used av_get_audio_frame_duration2() the estimate the desired packet size, but for some codecs that returns the duration of a single audio frame regardless of frame_bytes. - Fallback to 4096/block_align*block_align if bitrate is not available. Signed-off-by: Marton Balint <cus@passwd.hu>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/pcm.c41
-rw-r--r--libavformat/pcm.h1
2 files changed, 30 insertions, 12 deletions
diff --git a/libavformat/pcm.c b/libavformat/pcm.c
index 9741f73667..9676da3251 100644
--- a/libavformat/pcm.c
+++ b/libavformat/pcm.c
@@ -24,27 +24,44 @@
#include "internal.h"
#include "pcm.h"
-#define RAW_SAMPLES 1024
+#define PCM_DEMUX_TARGET_FPS 25
-int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt)
+int ff_pcm_default_packet_size(AVCodecParameters *par)
{
- AVCodecParameters *par = s->streams[0]->codecpar;
- int ret, size;
+ int nb_samples, max_samples, bits_per_sample;
+ int64_t bitrate;
if (par->block_align <= 0)
return AVERROR(EINVAL);
- /*
- * Compute read size to complete a read every 62ms.
- * Clamp to RAW_SAMPLES if larger.
- */
- size = FFMAX(par->sample_rate/25, 1);
- if (par->block_align <= INT_MAX / RAW_SAMPLES) {
- size = FFMIN(size, RAW_SAMPLES) * par->block_align;
+ max_samples = INT_MAX / par->block_align;
+ bits_per_sample = av_get_bits_per_sample(par->codec_id);
+ bitrate = par->bit_rate;
+
+ /* Don't trust the codecpar bitrate if we can calculate it ourselves */
+ if (bits_per_sample > 0 && par->sample_rate > 0 && par->ch_layout.nb_channels > 0)
+ if ((int64_t)par->sample_rate * par->ch_layout.nb_channels < INT64_MAX / bits_per_sample)
+ bitrate = bits_per_sample * par->sample_rate * par->ch_layout.nb_channels;
+
+ if (bitrate > 0) {
+ nb_samples = av_clip64(bitrate / 8 / PCM_DEMUX_TARGET_FPS / par->block_align, 1, max_samples);
+ nb_samples = 1 << av_log2(nb_samples);
} else {
- size = par->block_align;
+ /* Fallback to a size based method for a non-pcm codec with unknown bitrate */
+ nb_samples = av_clip(4096 / par->block_align, 1, max_samples);
}
+ return par->block_align * nb_samples;
+}
+
+int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ int ret, size;
+
+ size = ff_pcm_default_packet_size(s->streams[0]->codecpar);
+ if (size < 0)
+ return size;
+
ret = av_get_packet(s->pb, pkt, size);
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
diff --git a/libavformat/pcm.h b/libavformat/pcm.h
index 9af36d5a2e..1928497eed 100644
--- a/libavformat/pcm.h
+++ b/libavformat/pcm.h
@@ -24,6 +24,7 @@
#include "avformat.h"
+int ff_pcm_default_packet_size(AVCodecParameters *par);
int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt);
int ff_pcm_read_seek(AVFormatContext *s,
int stream_index, int64_t timestamp, int flags);