summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2012-01-26 20:08:23 -0500
committerJustin Ruggles <justin.ruggles@gmail.com>2012-03-05 13:08:15 -0500
commit9524cf79df9f4f5792272e7e53f7dcc90ee26e61 (patch)
tree76861289a8b6392cbfe429d836b877ae697b1499
parent6699d07480f58bc20068b2d90fcd6ca8e3aa46b8 (diff)
avcodec: add av_get_audio_frame_duration() function.
This is a utility function for the user to get the frame duration based on the codec id, frame size in bytes, and various AVCodecContext parameters.
-rw-r--r--doc/APIchanges4
-rw-r--r--libavcodec/avcodec.h10
-rw-r--r--libavcodec/utils.c142
-rw-r--r--libavcodec/version.h2
4 files changed, 157 insertions, 1 deletions
diff --git a/doc/APIchanges b/doc/APIchanges
index ef630e8e2a..c3755299dc 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -12,6 +12,10 @@ libavutil: 2011-04-18
API changes, most recent first:
+2012-xx-xx - lavc 54.8.0
+ xxxxxxx Add av_get_exact_bits_per_sample()
+ xxxxxxx Add av_get_audio_frame_duration()
+
2012-03-xx - xxxxxxx - lavc 54.7.0 - avcodec.h
Add av_codec_is_encoder/decoder().
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index bdd72f7d5c..7074b582ec 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3942,6 +3942,16 @@ int av_get_bits_per_sample(enum CodecID codec_id);
*/
int av_get_exact_bits_per_sample(enum CodecID codec_id);
+/**
+ * Return audio frame duration.
+ *
+ * @param avctx codec context
+ * @param frame_bytes size of the frame, or 0 if unknown
+ * @return frame duration, in samples, if known. 0 if not able to
+ * determine.
+ */
+int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes);
+
/* frame parsing */
typedef struct AVCodecParserContext {
void *priv_data;
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 458b1f358b..20e9687c9b 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1742,6 +1742,148 @@ int av_get_bits_per_sample(enum CodecID codec_id)
}
}
+int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
+{
+ int id, sr, ch, ba, tag, bps;
+
+ id = avctx->codec_id;
+ sr = avctx->sample_rate;
+ ch = avctx->channels;
+ ba = avctx->block_align;
+ tag = avctx->codec_tag;
+ bps = av_get_exact_bits_per_sample(avctx->codec_id);
+
+ /* codecs with an exact constant bits per sample */
+ if (bps > 0 && ch > 0 && frame_bytes > 0)
+ return (frame_bytes * 8) / (bps * ch);
+ bps = avctx->bits_per_coded_sample;
+
+ /* codecs with a fixed packet duration */
+ switch (id) {
+ case CODEC_ID_ADPCM_ADX: return 32;
+ case CODEC_ID_ADPCM_IMA_QT: return 64;
+ case CODEC_ID_ADPCM_EA_XAS: return 128;
+ case CODEC_ID_AMR_NB:
+ case CODEC_ID_GSM:
+ case CODEC_ID_QCELP:
+ case CODEC_ID_RA_144:
+ case CODEC_ID_RA_288: return 160;
+ case CODEC_ID_IMC: return 256;
+ case CODEC_ID_AMR_WB:
+ case CODEC_ID_GSM_MS: return 320;
+ case CODEC_ID_MP1: return 384;
+ case CODEC_ID_ATRAC1: return 512;
+ case CODEC_ID_ATRAC3: return 1024;
+ case CODEC_ID_MP2:
+ case CODEC_ID_MUSEPACK7: return 1152;
+ case CODEC_ID_AC3: return 1536;
+ }
+
+ if (sr > 0) {
+ /* calc from sample rate */
+ if (id == CODEC_ID_TTA)
+ return 256 * sr / 245;
+
+ if (ch > 0) {
+ /* calc from sample rate and channels */
+ if (id == CODEC_ID_BINKAUDIO_DCT)
+ return (480 << (sr / 22050)) / ch;
+ }
+ }
+
+ if (ba > 0) {
+ /* calc from block_align */
+ if (id == CODEC_ID_SIPR) {
+ switch (ba) {
+ case 20: return 160;
+ case 19: return 144;
+ case 29: return 288;
+ case 37: return 480;
+ }
+ }
+ }
+
+ if (frame_bytes > 0) {
+ /* calc from frame_bytes only */
+ if (id == CODEC_ID_TRUESPEECH)
+ return 240 * (frame_bytes / 32);
+ if (id == CODEC_ID_NELLYMOSER)
+ return 256 * (frame_bytes / 64);
+
+ if (bps > 0) {
+ /* calc from frame_bytes and bits_per_coded_sample */
+ if (id == CODEC_ID_ADPCM_G726)
+ return frame_bytes * 8 / bps;
+ }
+
+ if (ch > 0) {
+ /* calc from frame_bytes and channels */
+ switch (id) {
+ case CODEC_ID_ADPCM_4XM:
+ case CODEC_ID_ADPCM_IMA_ISS:
+ return (frame_bytes - 4 * ch) * 2 / ch;
+ case CODEC_ID_ADPCM_IMA_SMJPEG:
+ return (frame_bytes - 4) * 2 / ch;
+ case CODEC_ID_ADPCM_IMA_AMV:
+ return (frame_bytes - 8) * 2 / ch;
+ case CODEC_ID_ADPCM_XA:
+ return (frame_bytes / 128) * 224 / ch;
+ case CODEC_ID_INTERPLAY_DPCM:
+ return (frame_bytes - 6 - ch) / ch;
+ case CODEC_ID_ROQ_DPCM:
+ return (frame_bytes - 8) / ch;
+ case CODEC_ID_XAN_DPCM:
+ return (frame_bytes - 2 * ch) / ch;
+ case CODEC_ID_MACE3:
+ return 3 * frame_bytes / ch;
+ case CODEC_ID_MACE6:
+ return 6 * frame_bytes / ch;
+ case CODEC_ID_PCM_LXF:
+ return 2 * (frame_bytes / (5 * ch));
+ }
+
+ if (tag) {
+ /* calc from frame_bytes, channels, and codec_tag */
+ if (id == CODEC_ID_SOL_DPCM) {
+ if (tag == 3)
+ return frame_bytes / ch;
+ else
+ return frame_bytes * 2 / ch;
+ }
+ }
+
+ if (ba > 0) {
+ /* calc from frame_bytes, channels, and block_align */
+ int blocks = frame_bytes / ba;
+ switch (avctx->codec_id) {
+ case CODEC_ID_ADPCM_IMA_WAV:
+ return blocks * (1 + (ba - 4 * ch) / (4 * ch) * 8);
+ case CODEC_ID_ADPCM_IMA_DK3:
+ return blocks * (((ba - 16) * 8 / 3) / ch);
+ case CODEC_ID_ADPCM_IMA_DK4:
+ return blocks * (1 + (ba - 4 * ch) * 2 / ch);
+ case CODEC_ID_ADPCM_MS:
+ return blocks * (2 + (ba - 7 * ch) * 2 / ch);
+ }
+ }
+
+ if (bps > 0) {
+ /* calc from frame_bytes, channels, and bits_per_coded_sample */
+ switch (avctx->codec_id) {
+ case CODEC_ID_PCM_DVD:
+ return 2 * (frame_bytes / ((bps * 2 / 8) * ch));
+ case CODEC_ID_PCM_BLURAY:
+ return frame_bytes / ((FFALIGN(ch, 2) * bps) / 8);
+ case CODEC_ID_S302M:
+ return 2 * (frame_bytes / ((bps + 4) / 4)) / ch;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
#if !HAVE_THREADS
int ff_thread_init(AVCodecContext *s){
return -1;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 1ecfb215f6..2398cca2ae 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,7 +21,7 @@
#define AVCODEC_VERSION_H
#define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 7
+#define LIBAVCODEC_VERSION_MINOR 8
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \