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, \