X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Futils.c;h=e918024ca5626796d1dc690488b0f88781ac05cf;hb=532f1c7aa7390af5e5de2892481041000e4d872b;hp=74206720ca607ac0d8317e20d45b04de908ac2e4;hpb=d77294c5e404c8a214da0e74f7836390b48b2dba;p=ffmpeg diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 74206720ca6..e918024ca56 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -115,15 +115,15 @@ static void avcodec_init(void) return; initialized = 1; - dsputil_static_init(); + ff_dsputil_static_init(); } -static av_always_inline int codec_is_encoder(AVCodec *codec) +int av_codec_is_encoder(AVCodec *codec) { return codec && (codec->encode || codec->encode2); } -static av_always_inline int codec_is_decoder(AVCodec *codec) +int av_codec_is_decoder(AVCodec *codec) { return codec && codec->decode; } @@ -178,6 +178,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, case PIX_FMT_YUVJ440P: case PIX_FMT_YUVJ444P: case PIX_FMT_YUVA420P: + case PIX_FMT_YUVA444P: case PIX_FMT_YUV420P9LE: case PIX_FMT_YUV420P9BE: case PIX_FMT_YUV420P10LE: @@ -244,18 +245,6 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, for (i = 0; i < 4; i++) linesize_align[i] = STRIDE_ALIGN; -//STRIDE_ALIGN is 8 for SSE* but this does not work for SVQ1 chroma planes -//we could change STRIDE_ALIGN to 16 for x86/sse but it would increase the -//picture size unneccessarily in some cases. The solution here is not -//pretty and better ideas are welcome! -#if HAVE_MMX - if(s->codec_id == CODEC_ID_SVQ1 || s->codec_id == CODEC_ID_VP5 || - s->codec_id == CODEC_ID_VP6 || s->codec_id == CODEC_ID_VP6F || - s->codec_id == CODEC_ID_VP6A || s->codec_id == CODEC_ID_DIRAC) { - for (i = 0; i < 4; i++) - linesize_align[i] = 16; - } -#endif } void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ @@ -308,7 +297,7 @@ int avcodec_fill_audio_frame(AVFrame *frame, int nb_channels, } if ((ret = av_samples_fill_arrays(frame->extended_data, &frame->linesize[0], - buf, nb_channels, frame->nb_samples, + (uint8_t *)(intptr_t)buf, nb_channels, frame->nb_samples, sample_fmt, align)) < 0) { if (frame->extended_data != frame->data) av_freep(&frame->extended_data); @@ -425,7 +414,7 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) return -1; } - if(av_image_check_size(w, h, 0, s)) + if(av_image_check_size(w, h, 0, s) || s->pix_fmt<0) return -1; if (!avci->buffer) { @@ -614,6 +603,8 @@ int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){ return s->get_buffer(s, pic); } + assert(s->pix_fmt == pic->format); + /* If internal buffer type return the same buffer */ if(pic->type == FF_BUFFER_TYPE_INTERNAL) { return 0; @@ -688,6 +679,29 @@ static void avcodec_get_subtitle_defaults(AVSubtitle *sub) sub->pts = AV_NOPTS_VALUE; } +static int get_bit_rate(AVCodecContext *ctx) +{ + int bit_rate; + int bits_per_sample; + + switch(ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_SUBTITLE: + case AVMEDIA_TYPE_ATTACHMENT: + bit_rate = ctx->bit_rate; + break; + case AVMEDIA_TYPE_AUDIO: + bits_per_sample = av_get_bits_per_sample(ctx->codec_id); + bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * bits_per_sample : ctx->bit_rate; + break; + default: + bit_rate = 0; + break; + } + return bit_rate; +} + #if FF_API_AVCODEC_OPEN int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) { @@ -748,7 +762,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD goto end; } if (codec->priv_class) { - *(AVClass**)avctx->priv_data= codec->priv_class; + *(const AVClass**)avctx->priv_data= codec->priv_class; av_opt_set_defaults(avctx->priv_data); } } @@ -784,7 +798,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD /* if the decoder init function was already called previously, free the already allocated subtitle_header before overwriting it */ - if (codec_is_decoder(codec)) + if (av_codec_is_decoder(codec)) av_freep(&avctx->subtitle_header); #define SANE_NB_CHANNELS 128U @@ -831,7 +845,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD ret = AVERROR(EINVAL); goto free_and_end; } - if (codec_is_encoder(avctx->codec)) { + if (av_codec_is_encoder(avctx->codec)) { int i; if (avctx->codec->sample_fmts) { for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) @@ -843,6 +857,16 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD goto free_and_end; } } + if (avctx->codec->pix_fmts) { + for (i = 0; avctx->codec->pix_fmts[i] != PIX_FMT_NONE; i++) + if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) + break; + if (avctx->codec->pix_fmts[i] == PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Specified pix_fmt is not supported\n"); + ret = AVERROR(EINVAL); + goto free_and_end; + } + } if (avctx->codec->supported_samplerates) { for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) @@ -890,6 +914,9 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD } } + if (av_codec_is_decoder(avctx->codec) && !avctx->bit_rate) + avctx->bit_rate = get_bit_rate(avctx); + ret=0; end: entangled_thread_counter--; @@ -912,37 +939,60 @@ free_and_end: goto end; } -int ff_alloc_packet(AVPacket *avpkt, int size) +int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int size) { - if (size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) + if (size < 0 || avpkt->size < 0 || size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Size %d invalid\n", size); return AVERROR(EINVAL); + } + + av_assert0(!avpkt->data || avpkt->data != avctx->internal->byte_buffer); + if (!avpkt->data || avpkt->size < size) { + av_fast_padded_malloc(&avctx->internal->byte_buffer, &avctx->internal->byte_buffer_size, size); + avpkt->data = avctx->internal->byte_buffer; + avpkt->size = avctx->internal->byte_buffer_size; + avpkt->destruct = NULL; + } if (avpkt->data) { - uint8_t *pkt_data; + void *destruct = avpkt->destruct; - if (avpkt->size < size) + if (avpkt->size < size) { + av_log(avctx, AV_LOG_ERROR, "User packet is too small (%d < %d)\n", avpkt->size, size); return AVERROR(EINVAL); + } - pkt_data = avpkt->data; av_init_packet(avpkt); - avpkt->data = pkt_data; + avpkt->destruct = destruct; avpkt->size = size; return 0; } else { - return av_new_packet(avpkt, size); + int ret = av_new_packet(avpkt, size); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "Failed to allocate packet of size %d\n", size); + return ret; } } +int ff_alloc_packet(AVPacket *avpkt, int size) +{ + return ff_alloc_packet2(NULL, avpkt, size); +} + int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { int ret; - int user_packet = !!avpkt->data; + AVPacket user_pkt = *avpkt; int nb_samples; + int needs_realloc = !user_pkt.data; + + *got_packet_ptr = 0; if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_free_packet(avpkt); av_init_packet(avpkt); avpkt->size = 0; return 0; @@ -963,14 +1013,18 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, } if (avctx->codec->encode2) { - *got_packet_ptr = 0; ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); - if (!ret && *got_packet_ptr && - !(avctx->codec->capabilities & CODEC_CAP_DELAY)) { - avpkt->pts = frame->pts; - avpkt->duration = av_rescale_q(frame->nb_samples, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + if (!ret && *got_packet_ptr) { + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) { + if (avpkt->pts == AV_NOPTS_VALUE) + avpkt->pts = frame->pts; + if (!avpkt->duration) + avpkt->duration = ff_samples_to_time_base(avctx, + frame->nb_samples); + } + avpkt->dts = avpkt->pts; + } else { + avpkt->size = 0; } } else { /* for compatibility with encoders not supporting encode2(), we need to @@ -978,7 +1032,7 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, the size otherwise */ int fs_tmp = 0; int buf_size = avpkt->size; - if (!user_packet) { + if (!user_pkt.data) { if (avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) { av_assert0(av_get_bits_per_sample(avctx->codec_id) != 0); if (!frame) @@ -991,10 +1045,10 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, implement encode2() */ buf_size = 2 * avctx->frame_size * avctx->channels * av_get_bytes_per_sample(avctx->sample_fmt); - buf_size += FF_MIN_BUFFER_SIZE; + buf_size += 2*FF_MIN_BUFFER_SIZE; } } - if ((ret = ff_alloc_packet(avpkt, buf_size))) + if ((ret = ff_alloc_packet2(avctx, avpkt, buf_size))) return ret; /* Encoders using AVCodec.encode() that support @@ -1015,18 +1069,17 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, if (!ret) { /* no output. if the packet data was allocated by libavcodec, free it */ - if (!user_packet) + if (!user_pkt.data && avpkt->data != avctx->internal->byte_buffer) av_freep(&avpkt->data); } else { if (avctx->coded_frame) - avpkt->pts = avctx->coded_frame->pts; + avpkt->pts = avpkt->dts = avctx->coded_frame->pts; /* Set duration for final small packet. This can be removed once all encoders supporting CODEC_CAP_SMALL_LAST_FRAME use encode2() */ if (fs_tmp) { - avpkt->duration = av_rescale_q(avctx->frame_size, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + avpkt->duration = ff_samples_to_time_base(avctx, + avctx->frame_size); } } avpkt->size = ret; @@ -1037,8 +1090,37 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, if (fs_tmp) avctx->frame_size = fs_tmp; } - if (!ret) + if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { + needs_realloc = 0; + if (user_pkt.data) { + if (user_pkt.size >= avpkt->size) { + memcpy(user_pkt.data, avpkt->data, avpkt->size); + } else { + av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); + avpkt->size = user_pkt.size; + ret = -1; + } + avpkt->data = user_pkt.data; + avpkt->destruct = user_pkt.destruct; + } else { + if (av_dup_packet(avpkt) < 0) { + ret = AVERROR(ENOMEM); + } + } + } + + if (!ret) { + if (needs_realloc && avpkt->data) { + uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (new_data) + avpkt->data = new_data; + } + avctx->frame_number++; + } + + if (ret < 0 || !*got_packet_ptr) + av_free_packet(avpkt); /* NOTE: if we add any audio encoders which output non-keyframe packets, this needs to be moved to the encoders, but for now we can do it @@ -1092,16 +1174,15 @@ int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, avctx->sample_fmt, 1); if ((ret = avcodec_fill_audio_frame(frame, avctx->channels, avctx->sample_fmt, - samples, samples_size, 1))) + (const uint8_t *)samples, samples_size, 1))) return ret; /* fabricate frame pts from sample count. this is needed because the avcodec_encode_audio() API does not have a way for the user to provide pts */ if(avctx->sample_rate && avctx->time_base.num) - frame->pts = av_rescale_q(avctx->internal->sample_count, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + frame->pts = ff_samples_to_time_base(avctx, + avctx->internal->sample_count); else frame->pts = AV_NOPTS_VALUE; avctx->internal->sample_count += frame->nb_samples; @@ -1125,23 +1206,107 @@ int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, } #endif +#if FF_API_OLD_ENCODE_VIDEO int attribute_align_arg avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVFrame *pict) { + AVPacket pkt; + int ret, got_packet = 0; + if(buf_size < FF_MIN_BUFFER_SIZE){ av_log(avctx, AV_LOG_ERROR, "buffer smaller than minimum size\n"); return -1; } - if(av_image_check_size(avctx->width, avctx->height, 0, avctx)) - return -1; - if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){ - int ret = avctx->codec->encode(avctx, buf, buf_size, pict); - avctx->frame_number++; - emms_c(); //needed to avoid an emms_c() call before every return; - return ret; - }else + av_init_packet(&pkt); + pkt.data = buf; + pkt.size = buf_size; + + ret = avcodec_encode_video2(avctx, &pkt, pict, &got_packet); + if (!ret && got_packet && avctx->coded_frame) { + avctx->coded_frame->pts = pkt.pts; + avctx->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + return ret ? ret : pkt.size; +} +#endif + +int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx, + AVPacket *avpkt, + const AVFrame *frame, + int *got_packet_ptr) +{ + int ret; + AVPacket user_pkt = *avpkt; + int needs_realloc = !user_pkt.data; + + *got_packet_ptr = 0; + + if (!(avctx->codec->capabilities & CODEC_CAP_DELAY) && !frame) { + av_free_packet(avpkt); + av_init_packet(avpkt); + avpkt->size = 0; return 0; + } + + if (av_image_check_size(avctx->width, avctx->height, 0, avctx)) + return AVERROR(EINVAL); + + av_assert0(avctx->codec->encode2); + + ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr); + av_assert0(ret <= 0); + + if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) { + needs_realloc = 0; + if (user_pkt.data) { + if (user_pkt.size >= avpkt->size) { + memcpy(user_pkt.data, avpkt->data, avpkt->size); + } else { + av_log(avctx, AV_LOG_ERROR, "Provided packet is too small, needs to be %d\n", avpkt->size); + avpkt->size = user_pkt.size; + ret = -1; + } + avpkt->data = user_pkt.data; + avpkt->destruct = user_pkt.destruct; + } else { + if (av_dup_packet(avpkt) < 0) { + ret = AVERROR(ENOMEM); + } + } + } + + if (!ret) { + if (!*got_packet_ptr) + avpkt->size = 0; + else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) + avpkt->pts = avpkt->dts = frame->pts; + + if (needs_realloc && avpkt->data && + avpkt->destruct == av_destruct_packet) { + uint8_t *new_data = av_realloc(avpkt->data, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); + if (new_data) + avpkt->data = new_data; + } + + avctx->frame_number++; + } + + if (ret < 0 || !*got_packet_ptr) + av_free_packet(avpkt); + + emms_c(); + return ret; } int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, @@ -1153,7 +1318,7 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, return -1; } - ret = avctx->codec->encode(avctx, buf, buf_size, sub); + ret = avctx->codec->encode(avctx, buf, buf_size, (void *)(intptr_t)sub); avctx->frame_number++; return ret; } @@ -1423,6 +1588,8 @@ av_cold int avcodec_close(AVCodecContext *avctx) avctx->codec->close(avctx); avcodec_default_free_buffers(avctx); avctx->coded_frame = NULL; + avctx->internal->byte_buffer_size = 0; + av_freep(&avctx->internal->byte_buffer); av_freep(&avctx->internal); } @@ -1430,7 +1597,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_opt_free(avctx->priv_data); av_opt_free(avctx); av_freep(&avctx->priv_data); - if (codec_is_encoder(avctx->codec)) + if (av_codec_is_encoder(avctx->codec)) av_freep(&avctx->extradata); avctx->codec = NULL; avctx->active_thread_type = 0; @@ -1459,7 +1626,7 @@ AVCodec *avcodec_find_encoder(enum CodecID id) p = first_avcodec; id= remap_deprecated_codec_id(id); while (p) { - if (codec_is_encoder(p) && p->id == id) { + if (av_codec_is_encoder(p) && p->id == id) { if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { experimental = p; } else @@ -1477,7 +1644,7 @@ AVCodec *avcodec_find_encoder_by_name(const char *name) return NULL; p = first_avcodec; while (p) { - if (codec_is_encoder(p) && strcmp(name,p->name) == 0) + if (av_codec_is_encoder(p) && strcmp(name,p->name) == 0) return p; p = p->next; } @@ -1490,7 +1657,7 @@ AVCodec *avcodec_find_decoder(enum CodecID id) p = first_avcodec; id= remap_deprecated_codec_id(id); while (p) { - if (codec_is_decoder(p) && p->id == id) { + if (av_codec_is_decoder(p) && p->id == id) { if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { experimental = p; } else @@ -1508,36 +1675,13 @@ AVCodec *avcodec_find_decoder_by_name(const char *name) return NULL; p = first_avcodec; while (p) { - if (codec_is_decoder(p) && strcmp(name,p->name) == 0) + if (av_codec_is_decoder(p) && strcmp(name,p->name) == 0) return p; p = p->next; } return NULL; } -static int get_bit_rate(AVCodecContext *ctx) -{ - int bit_rate; - int bits_per_sample; - - switch(ctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - case AVMEDIA_TYPE_DATA: - case AVMEDIA_TYPE_SUBTITLE: - case AVMEDIA_TYPE_ATTACHMENT: - bit_rate = ctx->bit_rate; - break; - case AVMEDIA_TYPE_AUDIO: - bits_per_sample = av_get_bits_per_sample(ctx->codec_id); - bit_rate = bits_per_sample ? ctx->sample_rate * ctx->channels * bits_per_sample : ctx->bit_rate; - break; - default: - bit_rate = 0; - break; - } - return bit_rate; -} - const char *avcodec_get_name(enum CodecID id) { AVCodec *codec; @@ -1764,21 +1908,15 @@ void avcodec_default_free_buffers(AVCodecContext *avctx) } } -int av_get_bits_per_sample(enum CodecID codec_id){ +int av_get_exact_bits_per_sample(enum CodecID codec_id) +{ switch(codec_id){ - case CODEC_ID_ADPCM_SBPRO_2: - return 2; - case CODEC_ID_ADPCM_SBPRO_3: - return 3; - case CODEC_ID_ADPCM_SBPRO_4: case CODEC_ID_ADPCM_CT: case CODEC_ID_ADPCM_IMA_APC: - case CODEC_ID_ADPCM_IMA_WAV: - case CODEC_ID_ADPCM_IMA_QT: - case CODEC_ID_ADPCM_SWF: - case CODEC_ID_ADPCM_MS: - case CODEC_ID_ADPCM_YAMAHA: + case CODEC_ID_ADPCM_IMA_EA_SEAD: + case CODEC_ID_ADPCM_IMA_WS: case CODEC_ID_ADPCM_G722: + case CODEC_ID_ADPCM_YAMAHA: return 4; case CODEC_ID_PCM_ALAW: case CODEC_ID_PCM_MULAW: @@ -1813,6 +1951,187 @@ int av_get_bits_per_sample(enum CodecID codec_id){ } } +enum CodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be) +{ + static const enum CodecID map[AV_SAMPLE_FMT_NB][2] = { + [AV_SAMPLE_FMT_U8 ] = { CODEC_ID_PCM_U8, CODEC_ID_PCM_U8 }, + [AV_SAMPLE_FMT_S16 ] = { CODEC_ID_PCM_S16LE, CODEC_ID_PCM_S16BE }, + [AV_SAMPLE_FMT_S32 ] = { CODEC_ID_PCM_S32LE, CODEC_ID_PCM_S32BE }, + [AV_SAMPLE_FMT_FLT ] = { CODEC_ID_PCM_F32LE, CODEC_ID_PCM_F32BE }, + [AV_SAMPLE_FMT_DBL ] = { CODEC_ID_PCM_F64LE, CODEC_ID_PCM_F64BE }, + [AV_SAMPLE_FMT_U8P ] = { CODEC_ID_PCM_U8, CODEC_ID_PCM_U8 }, + [AV_SAMPLE_FMT_S16P] = { CODEC_ID_PCM_S16LE, CODEC_ID_PCM_S16BE }, + [AV_SAMPLE_FMT_S32P] = { CODEC_ID_PCM_S32LE, CODEC_ID_PCM_S32BE }, + [AV_SAMPLE_FMT_FLTP] = { CODEC_ID_PCM_F32LE, CODEC_ID_PCM_F32BE }, + [AV_SAMPLE_FMT_DBLP] = { CODEC_ID_PCM_F64LE, CODEC_ID_PCM_F64BE }, + }; + if (fmt < 0 || fmt >= AV_SAMPLE_FMT_NB) + return CODEC_ID_NONE; + if (be < 0 || be > 1) + be = AV_NE(1, 0); + return map[fmt][be]; +} + +int av_get_bits_per_sample(enum CodecID codec_id) +{ + switch (codec_id) { + case CODEC_ID_ADPCM_SBPRO_2: + return 2; + case CODEC_ID_ADPCM_SBPRO_3: + return 3; + case CODEC_ID_ADPCM_SBPRO_4: + case CODEC_ID_ADPCM_IMA_WAV: + case CODEC_ID_ADPCM_IMA_QT: + case CODEC_ID_ADPCM_SWF: + case CODEC_ID_ADPCM_MS: + return 4; + default: + return av_get_exact_bits_per_sample(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) * 2 / 3 * 4) / 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;