summaryrefslogtreecommitdiff
path: root/libavcodec/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/utils.c')
-rw-r--r--libavcodec/utils.c235
1 files changed, 166 insertions, 69 deletions
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index c1a5c19e04..205e3600c5 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
*/
@@ -166,7 +166,7 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l
case PIX_FMT_YUV444P10BE:
w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
h_align= 16;
- if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264)
+ if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264 || s->codec_id == CODEC_ID_PRORES)
h_align= 32; // interlaced is rounded up to 2 MBs
break;
case PIX_FMT_YUV411P:
@@ -241,6 +241,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;
+}
+
int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
int i;
int w= s->width;
@@ -365,9 +381,18 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
}
s->internal_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 buffers used\n", pic, s->internal_buffer_count);
@@ -471,8 +496,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->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){
@@ -485,6 +513,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)
{
@@ -575,6 +609,9 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD
}
avctx->frame_number = 0;
+ 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) {
@@ -582,11 +619,10 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD
}
}
- if (avctx->codec->max_lowres < avctx->lowres) {
- av_log(avctx, AV_LOG_ERROR, "The maximum value for lowres supported by the decoder is %d\n",
+ if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
+ av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
avctx->codec->max_lowres);
- ret = AVERROR(EINVAL);
- goto free_and_end;
+ avctx->lowres = avctx->codec->max_lowres;
}
if (avctx->codec->encode) {
int i;
@@ -635,12 +671,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--;
@@ -703,13 +746,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)
@@ -720,9 +794,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);
@@ -730,12 +804,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;
@@ -784,6 +876,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++;
@@ -880,14 +973,18 @@ 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;
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)
@@ -927,6 +1024,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;
@@ -944,43 +1060,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",
@@ -996,7 +1106,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);
}
@@ -1013,12 +1123,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);
@@ -1030,17 +1134,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) {
@@ -1078,13 +1172,13 @@ unsigned avcodec_version( void )
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)
@@ -1202,7 +1296,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);
@@ -1219,8 +1313,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);
}
@@ -1282,6 +1376,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);
}