diff options
Diffstat (limited to 'libavcodec/utils.c')
-rw-r--r-- | libavcodec/utils.c | 302 |
1 files changed, 223 insertions, 79 deletions
diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 7e9ddb2e35..4e0a2f8710 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -3,20 +3,20 @@ * Copyright (c) 2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -33,6 +33,7 @@ #include "libavutil/imgutils.h" #include "libavutil/samplefmt.h" #include "libavutil/dict.h" +#include "libavutil/avassert.h" #include "avcodec.h" #include "dsputil.h" #include "libavutil/opt.h" @@ -205,6 +206,10 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, break; } + if(s->codec_id == CODEC_ID_IFF_ILBM || s->codec_id == CODEC_ID_IFF_BYTERUN1){ + w_align= FFMAX(w_align, 8); + } + *width = FFALIGN(*width , w_align); *height= FFALIGN(*height, h_align); if(s->codec_id == CODEC_ID_H264 || s->lowres) @@ -220,7 +225,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, #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_VP6A || s->codec_id == CODEC_ID_DIRAC) { for (i = 0; i < AV_NUM_DATA_POINTERS; i++) linesize_align[i] = 16; } @@ -239,6 +244,22 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ *width=FFALIGN(*width, align); } +void ff_init_buffer_info(AVCodecContext *s, AVFrame *pic) +{ + if (s->pkt) { + pic->pkt_pts = s->pkt->pts; + pic->pkt_pos = s->pkt->pos; + } else { + pic->pkt_pts = AV_NOPTS_VALUE; + pic->pkt_pos = -1; + } + pic->reordered_opaque= s->reordered_opaque; + pic->sample_aspect_ratio = s->sample_aspect_ratio; + pic->width = s->width; + pic->height = s->height; + pic->format = s->pix_fmt; +} + static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) { AVCodecInternal *avci = avctx->internal; @@ -328,8 +349,14 @@ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) frame->linesize[0] = buf->linesize[0]; memcpy(frame->data, buf->data, sizeof(frame->data)); - if (avctx->pkt) frame->pkt_pts = avctx->pkt->pts; - else frame->pkt_pts = AV_NOPTS_VALUE; + if (avctx->pkt) { + frame->pkt_pts = avctx->pkt->pts; + frame->pkt_pos = avctx->pkt->pos; + } else { + frame->pkt_pts = AV_NOPTS_VALUE; + frame->pkt_pos = -1; + } + frame->reordered_opaque = avctx->reordered_opaque; if (avctx->debug & FF_DEBUG_BUFFERS) @@ -456,9 +483,18 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic) pic->extended_data = pic->data; avci->buffer_count++; - if(s->pkt) pic->pkt_pts= s->pkt->pts; - else pic->pkt_pts= AV_NOPTS_VALUE; + if (s->pkt) { + pic->pkt_pts = s->pkt->pts; + pic->pkt_pos = s->pkt->pos; + } else { + pic->pkt_pts = AV_NOPTS_VALUE; + pic->pkt_pos = -1; + } pic->reordered_opaque= s->reordered_opaque; + pic->sample_aspect_ratio = s->sample_aspect_ratio; + pic->width = s->width; + pic->height = s->height; + pic->format = s->pix_fmt; if(s->debug&FF_DEBUG_BUFFERS) av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d " @@ -582,8 +618,11 @@ enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum void avcodec_get_frame_defaults(AVFrame *pic){ memset(pic, 0, sizeof(AVFrame)); - pic->pts= AV_NOPTS_VALUE; + pic->pts = pic->pkt_dts = pic->pkt_pts = pic->best_effort_timestamp = AV_NOPTS_VALUE; + pic->pkt_pos = -1; pic->key_frame= 1; + pic->sample_aspect_ratio = (AVRational){0, 1}; + pic->format = -1; /* unknown */ } AVFrame *avcodec_alloc_frame(void){ @@ -596,6 +635,12 @@ AVFrame *avcodec_alloc_frame(void){ return pic; } +static void avcodec_get_subtitle_defaults(AVSubtitle *sub) +{ + memset(sub, 0, sizeof(*sub)); + sub->pts = AV_NOPTS_VALUE; +} + #if FF_API_AVCODEC_OPEN int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) { @@ -655,10 +700,13 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD if ((ret = av_opt_set_dict(avctx, &tmp)) < 0) goto free_and_end; + //We only call avcodec_set_dimensions() for non h264 codecs so as not to overwrite previously setup dimensions + if(!( avctx->coded_width && avctx->coded_height && avctx->width && avctx->height && avctx->codec_id == CODEC_ID_H264)){ if(avctx->coded_width && avctx->coded_height) avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height); else if(avctx->width && avctx->height) avcodec_set_dimensions(avctx, avctx->width, avctx->height); + } if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height) && ( av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0 @@ -693,15 +741,24 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD avctx->frame_number = 0; #if FF_API_ER - av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition separate: %d; %d\n", + av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition separate: %d; %X\n", avctx->error_recognition, avctx->err_recognition); - /* FF_ER_CAREFUL (==1) implies AV_EF_CRCCHECK (== 1<<1 - 1), - FF_ER_COMPLIANT (==2) implies AV_EF_{CRCCHECK,BITSTREAM} (== 1<<2 - 1), et cetera} */ - avctx->err_recognition |= (1<<(avctx->error_recognition-(avctx->error_recognition>=FF_ER_VERY_AGGRESSIVE))) - 1; - av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition combined: %d; %d\n", + switch(avctx->error_recognition){ + case FF_ER_EXPLODE : avctx->err_recognition |= AV_EF_EXPLODE | AV_EF_COMPLIANT | AV_EF_CAREFUL; + break; + case FF_ER_VERY_AGGRESSIVE: + case FF_ER_AGGRESSIVE : avctx->err_recognition |= AV_EF_AGGRESSIVE; + case FF_ER_COMPLIANT : avctx->err_recognition |= AV_EF_COMPLIANT; + case FF_ER_CAREFUL : avctx->err_recognition |= AV_EF_CAREFUL; + } + + av_log(avctx, AV_LOG_DEBUG, "err{or,}_recognition combined: %d; %X\n", avctx->error_recognition, avctx->err_recognition); #endif + if (!HAVE_THREADS) + av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n"); + if (HAVE_THREADS && !avctx->thread_opaque) { ret = ff_thread_init(avctx); if (ret < 0) { @@ -709,7 +766,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD } } - if (avctx->codec->max_lowres < avctx->lowres) { + if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) { av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n", avctx->codec->max_lowres); ret = AVERROR(EINVAL); @@ -762,12 +819,19 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD } } + avctx->pts_correction_num_faulty_pts = + avctx->pts_correction_num_faulty_dts = 0; + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + if(avctx->codec->init && !(avctx->active_thread_type&FF_THREAD_FRAME)){ ret = avctx->codec->init(avctx); if (ret < 0) { goto free_and_end; } } + + ret=0; end: entangled_thread_counter--; @@ -831,13 +895,44 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, av_log(avctx, AV_LOG_ERROR, "start_display_time must be 0.\n"); return -1; } - if(sub->num_rects == 0 || !sub->rects) - return -1; + ret = avctx->codec->encode(avctx, buf, buf_size, sub); avctx->frame_number++; return ret; } +/** + * Attempt to guess proper monotonic timestamps for decoded video frames + * which might have incorrect times. Input timestamps may wrap around, in + * which case the output will as well. + * + * @param pts the pts field of the decoded AVPacket, as passed through + * AVFrame.pkt_pts + * @param dts the dts field of the decoded AVPacket + * @return one of the input values, may be AV_NOPTS_VALUE + */ +static int64_t guess_correct_pts(AVCodecContext *ctx, + int64_t reordered_pts, int64_t dts) +{ + int64_t pts = AV_NOPTS_VALUE; + + if (dts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_dts += dts <= ctx->pts_correction_last_dts; + ctx->pts_correction_last_dts = dts; + } + if (reordered_pts != AV_NOPTS_VALUE) { + ctx->pts_correction_num_faulty_pts += reordered_pts <= ctx->pts_correction_last_pts; + ctx->pts_correction_last_pts = reordered_pts; + } + if ((ctx->pts_correction_num_faulty_pts<=ctx->pts_correction_num_faulty_dts || dts == AV_NOPTS_VALUE) + && reordered_pts != AV_NOPTS_VALUE) + pts = reordered_pts; + else + pts = dts; + + return pts; +} + int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt) @@ -848,9 +943,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx)) return -1; - avctx->pkt = avpkt; - if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){ + av_packet_split_side_data(avpkt); + avctx->pkt = avpkt; if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME) ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr, avpkt); @@ -858,12 +953,30 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi ret = avctx->codec->decode(avctx, picture, got_picture_ptr, avpkt); picture->pkt_dts= avpkt->dts; + + if(!avctx->has_b_frames){ + picture->pkt_pos= avpkt->pos; + } + //FIXME these should be under if(!avctx->has_b_frames) + if (!picture->sample_aspect_ratio.num) + picture->sample_aspect_ratio = avctx->sample_aspect_ratio; + if (!picture->width) + picture->width = avctx->width; + if (!picture->height) + picture->height = avctx->height; + if (picture->format == PIX_FMT_NONE) + picture->format = avctx->pix_fmt; } emms_c(); //needed to avoid an emms_c() call before every return; - if (*got_picture_ptr) + + if (*got_picture_ptr){ avctx->frame_number++; + picture->best_effort_timestamp = guess_correct_pts(avctx, + picture->pkt_pts, + picture->pkt_dts); + } }else ret= 0; @@ -879,9 +992,10 @@ int attribute_align_arg avcodec_decode_audio3(AVCodecContext *avctx, int16_t *sa int ret, got_frame = 0; if (avctx->get_buffer != avcodec_default_get_buffer) { - av_log(avctx, AV_LOG_ERROR, "A custom get_buffer() cannot be used with " + av_log(avctx, AV_LOG_ERROR, "Overriding custom get_buffer() for " "avcodec_decode_audio3()\n"); - return AVERROR(EINVAL); + avctx->get_buffer = avcodec_default_get_buffer; + avctx->release_buffer = avcodec_default_release_buffer; } ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt); @@ -965,16 +1079,16 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx, *got_frame_ptr = 0; - avctx->pkt = avpkt; - if (!avpkt->data && avpkt->size) { av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n"); return AVERROR(EINVAL); } - apply_param_change(avctx, avpkt); - if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) { + av_packet_split_side_data(avpkt); + apply_param_change(avctx, avpkt); + + avctx->pkt = avpkt; ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt); if (ret >= 0 && *got_frame_ptr) { avctx->frame_number++; @@ -992,6 +1106,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, avctx->pkt = avpkt; *got_sub_ptr = 0; + avcodec_get_subtitle_defaults(sub); ret = avctx->codec->decode(avctx, sub, got_sub_ptr, avpkt); if (*got_sub_ptr) avctx->frame_number++; @@ -1057,10 +1172,21 @@ av_cold int avcodec_close(AVCodecContext *avctx) return 0; } +static enum CodecID remap_deprecated_codec_id(enum CodecID id) +{ + switch(id){ + case CODEC_ID_G723_1_DEPRECATED : return CODEC_ID_G723_1; + case CODEC_ID_G729_DEPRECATED : return CODEC_ID_G729; + case CODEC_ID_UTVIDEO_DEPRECATED: return CODEC_ID_UTVIDEO; + default : return id; + } +} + AVCodec *avcodec_find_encoder(enum CodecID id) { AVCodec *p, *experimental=NULL; p = first_avcodec; + id= remap_deprecated_codec_id(id); while (p) { if (p->encode != NULL && p->id == id) { if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { @@ -1089,14 +1215,19 @@ AVCodec *avcodec_find_encoder_by_name(const char *name) AVCodec *avcodec_find_decoder(enum CodecID id) { - AVCodec *p; + AVCodec *p, *experimental=NULL; p = first_avcodec; + id= remap_deprecated_codec_id(id); while (p) { - if (p->decode != NULL && p->id == id) - return p; + if (p->decode != NULL && p->id == id) { + if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { + experimental = p; + } else + return p; + } p = p->next; } - return NULL; + return experimental; } AVCodec *avcodec_find_decoder_by_name(const char *name) @@ -1136,6 +1267,25 @@ static int get_bit_rate(AVCodecContext *ctx) return bit_rate; } +const char *avcodec_get_name(enum CodecID id) +{ + AVCodec *codec; + +#if !CONFIG_SMALL + switch (id) { +#include "libavcodec/codec_names.h" + } + av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id); +#endif + codec = avcodec_find_decoder(id); + if (codec) + return codec->name; + codec = avcodec_find_encoder(id); + if (codec) + return codec->name; + return "unknown_codec"; +} + size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_tag) { int i, len, ret = 0; @@ -1153,43 +1303,37 @@ size_t av_get_codec_tag_string(char *buf, size_t buf_size, unsigned int codec_ta void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) { + const char *codec_type; const char *codec_name; const char *profile = NULL; AVCodec *p; - char buf1[32]; int bitrate; AVRational display_aspect_ratio; - if (encode) - p = avcodec_find_encoder(enc->codec_id); - else - p = avcodec_find_decoder(enc->codec_id); - - if (p) { - codec_name = p->name; - profile = av_get_profile_name(p, enc->profile); - } else if (enc->codec_id == CODEC_ID_MPEG2TS) { - /* fake mpeg2 transport stream codec (currently not - registered) */ - codec_name = "mpeg2ts"; - } else if (enc->codec_name[0] != '\0') { - codec_name = enc->codec_name; - } else { - /* output avi tags */ + if (!buf || buf_size <= 0) + return; + codec_type = av_get_media_type_string(enc->codec_type); + codec_name = avcodec_get_name(enc->codec_id); + if (enc->profile != FF_PROFILE_UNKNOWN) { + p = encode ? avcodec_find_encoder(enc->codec_id) : + avcodec_find_decoder(enc->codec_id); + if (p) + profile = av_get_profile_name(p, enc->profile); + } + + snprintf(buf, buf_size, "%s: %s%s", codec_type ? codec_type : "unknown", + codec_name, enc->mb_decision ? " (hq)" : ""); + buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */ + if (profile) + snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile); + if (enc->codec_tag) { char tag_buf[32]; av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag); - snprintf(buf1, sizeof(buf1), "%s / 0x%04X", tag_buf, enc->codec_tag); - codec_name = buf1; + snprintf(buf + strlen(buf), buf_size - strlen(buf), + " (%s / 0x%04X)", tag_buf, enc->codec_tag); } - switch(enc->codec_type) { case AVMEDIA_TYPE_VIDEO: - snprintf(buf, buf_size, - "Video: %s%s", - codec_name, enc->mb_decision ? " (hq)" : ""); - if (profile) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - " (%s)", profile); if (enc->pix_fmt != PIX_FMT_NONE) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %s", @@ -1205,7 +1349,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) enc->height*enc->sample_aspect_ratio.den, 1024*1024); snprintf(buf + strlen(buf), buf_size - strlen(buf), - " [PAR %d:%d DAR %d:%d]", + " [SAR %d:%d DAR %d:%d]", enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den, display_aspect_ratio.num, display_aspect_ratio.den); } @@ -1222,12 +1366,6 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) } break; case AVMEDIA_TYPE_AUDIO: - snprintf(buf, buf_size, - "Audio: %s", - codec_name); - if (profile) - snprintf(buf + strlen(buf), buf_size - strlen(buf), - " (%s)", profile); if (enc->sample_rate) { snprintf(buf + strlen(buf), buf_size - strlen(buf), ", %d Hz", enc->sample_rate); @@ -1239,17 +1377,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) ", %s", av_get_sample_fmt_name(enc->sample_fmt)); } break; - case AVMEDIA_TYPE_DATA: - snprintf(buf, buf_size, "Data: %s", codec_name); - break; - case AVMEDIA_TYPE_SUBTITLE: - snprintf(buf, buf_size, "Subtitle: %s", codec_name); - break; - case AVMEDIA_TYPE_ATTACHMENT: - snprintf(buf, buf_size, "Attachment: %s", codec_name); - break; default: - snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type); return; } if (encode) { @@ -1282,18 +1410,25 @@ const char *av_get_profile_name(const AVCodec *codec, int profile) unsigned avcodec_version( void ) { + av_assert0(CODEC_ID_V410==164); + av_assert0(CODEC_ID_PCM_S8_PLANAR==65563); + av_assert0(CODEC_ID_ADPCM_G722==69660); + av_assert0(CODEC_ID_BMV_AUDIO==86071); + av_assert0(CODEC_ID_SRT==94216); + av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); + return LIBAVCODEC_VERSION_INT; } const char *avcodec_configuration(void) { - return LIBAV_CONFIGURATION; + return FFMPEG_CONFIGURATION; } const char *avcodec_license(void) { #define LICENSE_PREFIX "libavcodec license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } void avcodec_flush_buffers(AVCodecContext *avctx) @@ -1446,7 +1581,7 @@ int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b){ void av_log_missing_feature(void *avc, const char *feature, int want_sample) { - av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your Libav " + av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your FFmpeg " "version to the newest one from Git. If the problem still " "occurs, it means that your file has a feature which has not " "been implemented.\n", feature); @@ -1463,8 +1598,8 @@ void av_log_ask_for_sample(void *avc, const char *msg, ...) if (msg) av_vlog(avc, AV_LOG_WARNING, msg, argument_list); av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.libav.org/incoming/ " - "and contact the libav-devel mailing list.\n"); + "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ " + "and contact the ffmpeg-devel mailing list.\n"); va_end(argument_list); } @@ -1548,6 +1683,9 @@ unsigned int avpriv_toupper4(unsigned int x) int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f) { f->owner = avctx; + + ff_init_buffer_info(avctx, f); + return avctx->get_buffer(avctx, f); } @@ -1580,6 +1718,12 @@ int avcodec_thread_init(AVCodecContext *s, int thread_count) enum AVMediaType avcodec_get_type(enum CodecID codec_id) { + AVCodec *c= avcodec_find_decoder(codec_id); + if(!c) + c= avcodec_find_encoder(codec_id); + if(c) + return c->type; + if (codec_id <= CODEC_ID_NONE) return AVMEDIA_TYPE_UNKNOWN; else if (codec_id < CODEC_ID_FIRST_AUDIO) |