case PIX_FMT_YUVJ440P:
case PIX_FMT_YUVJ444P:
case PIX_FMT_YUVA420P:
+ case PIX_FMT_YUVA422P:
case PIX_FMT_YUVA444P:
case PIX_FMT_YUV420P9LE:
case PIX_FMT_YUV420P9BE:
buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
frame->nb_samples, avctx->sample_fmt,
- 32);
+ 0);
if (buf_size < 0)
return AVERROR(EINVAL);
}
if ((ret = avcodec_fill_audio_frame(frame, avctx->channels,
avctx->sample_fmt, buf->data[0],
- buf->audio_data_size, 32)))
+ buf->audio_data_size, 0)))
return ret;
if (frame->extended_data == frame->data)
frame->reordered_opaque = avctx->reordered_opaque;
+ frame->sample_rate = avctx->sample_rate;
+ frame->format = avctx->sample_fmt;
+ frame->channel_layout = avctx->channel_layout;
+
if (avctx->debug & FF_DEBUG_BUFFERS)
av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p, "
"internal audio buffer used\n", frame);
buf = &avci->buffer[avci->buffer_count];
if(buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt != s->pix_fmt)){
- if(s->active_thread_type&FF_THREAD_FRAME) {
- av_log_missing_feature(s, "Width/height changing with frame threads is", 0);
- return -1;
- }
-
for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
av_freep(&buf->base[i]);
buf->data[i]= NULL;
}
pic->extended_data = pic->data;
avci->buffer_count++;
+ pic->width = buf->width;
+ pic->height = buf->height;
+ pic->format = buf->pix_fmt;
+ pic->sample_aspect_ratio = s->sample_aspect_ratio;
if (s->pkt) {
pic->pkt_pts = s->pkt->pts;
InternalBuffer *buf, *last;
AVCodecInternal *avci = s->internal;
- assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
+ av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO);
assert(pic->type==FF_BUFFER_TYPE_INTERNAL);
assert(avci->buffer_count);
if (buf->data[0] == pic->data[0])
break;
}
- assert(i < avci->buffer_count);
+ av_assert0(i < avci->buffer_count);
avci->buffer_count--;
last = &avci->buffer[avci->buffer_count];
AVFrame temp_pic;
int i;
- assert(s->codec_type == AVMEDIA_TYPE_VIDEO);
+ av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO);
if (pic->data[0] && (pic->width != s->width || pic->height != s->height || pic->format != s->pix_fmt)) {
av_log(s, AV_LOG_WARNING, "Picture changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s in reget buffer()\n",
return pic;
}
+#define MAKE_ACCESSORS(str, name, type, field) \
+ type av_##name##_get_##field(const str *s) { return s->field; } \
+ void av_##name##_set_##field(str *s, type v) { s->field = v; }
+
+MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp)
+MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos)
+MAKE_ACCESSORS(AVFrame, frame, int64_t, channel_layout)
+MAKE_ACCESSORS(AVFrame, frame, int, sample_rate)
+
static void avcodec_get_subtitle_defaults(AVSubtitle *sub)
{
memset(sub, 0, sizeof(*sub));
ret = AVERROR(EINVAL);
goto free_and_end;
}
+
if (av_codec_is_encoder(avctx->codec)) {
int i;
if (avctx->codec->sample_fmts) {
}
}
- if (av_codec_is_decoder(avctx->codec) && !avctx->bit_rate)
- avctx->bit_rate = get_bit_rate(avctx);
-
ret=0;
+
+ if (av_codec_is_decoder(avctx->codec)) {
+ if (!avctx->bit_rate)
+ avctx->bit_rate = get_bit_rate(avctx);
+ /* validate channel layout from the decoder */
+ if (avctx->channel_layout &&
+ av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) {
+ av_log(avctx, AV_LOG_WARNING, "channel layout does not match number of channels\n");
+ avctx->channel_layout = 0;
+ }
+ }
end:
entangled_thread_counter--;
return ff_alloc_packet2(NULL, avpkt, size);
}
+/**
+ * Pad last frame with silence.
+ */
+static int pad_last_frame(AVCodecContext *s, AVFrame **dst, const AVFrame *src)
+{
+ AVFrame *frame = NULL;
+ uint8_t *buf = NULL;
+ int ret;
+
+ if (!(frame = avcodec_alloc_frame()))
+ return AVERROR(ENOMEM);
+ *frame = *src;
+
+ if ((ret = av_samples_get_buffer_size(&frame->linesize[0], s->channels,
+ s->frame_size, s->sample_fmt, 0)) < 0)
+ goto fail;
+
+ if (!(buf = av_malloc(ret))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ frame->nb_samples = s->frame_size;
+ if ((ret = avcodec_fill_audio_frame(frame, s->channels, s->sample_fmt,
+ buf, ret, 0)) < 0)
+ goto fail;
+ if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0,
+ src->nb_samples, s->channels, s->sample_fmt)) < 0)
+ goto fail;
+ if ((ret = av_samples_set_silence(frame->extended_data, src->nb_samples,
+ frame->nb_samples - src->nb_samples,
+ s->channels, s->sample_fmt)) < 0)
+ goto fail;
+
+ *dst = frame;
+
+ return 0;
+
+fail:
+ if (frame->extended_data != frame->data)
+ av_freep(&frame->extended_data);
+ av_freep(&buf);
+ av_freep(&frame);
+ return ret;
+}
+
int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
AVPacket *avpkt,
const AVFrame *frame,
int *got_packet_ptr)
{
+ AVFrame tmp;
+ AVFrame *padded_frame = NULL;
int ret;
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;
}
+ /* ensure that extended_data is properly set */
+ if (frame && !frame->extended_data) {
+ if (av_sample_fmt_is_planar(avctx->sample_fmt) &&
+ avctx->channels > AV_NUM_DATA_POINTERS) {
+ av_log(avctx, AV_LOG_ERROR, "Encoding to a planar sample format, "
+ "with more than %d channels, but extended_data is not set.\n",
+ AV_NUM_DATA_POINTERS);
+ return AVERROR(EINVAL);
+ }
+ av_log(avctx, AV_LOG_WARNING, "extended_data is not set.\n");
+
+ tmp = *frame;
+ tmp.extended_data = tmp.data;
+ frame = &tmp;
+ }
+
/* check for valid frame size */
if (frame) {
- nb_samples = frame->nb_samples;
if (avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
- if (nb_samples > avctx->frame_size)
+ if (frame->nb_samples > avctx->frame_size)
return AVERROR(EINVAL);
} else if (!(avctx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
- if (nb_samples != avctx->frame_size)
+ if (frame->nb_samples < avctx->frame_size &&
+ !avctx->internal->last_audio_frame) {
+ ret = pad_last_frame(avctx, &padded_frame, frame);
+ if (ret < 0)
+ return ret;
+
+ frame = padded_frame;
+ avctx->internal->last_audio_frame = 1;
+ }
+
+ if (frame->nb_samples != avctx->frame_size)
return AVERROR(EINVAL);
}
- } else {
- nb_samples = avctx->frame_size;
}
- if (avctx->codec->encode2) {
- ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr);
- if (!ret && *got_packet_ptr) {
+ ret = avctx->codec->encode2(avctx, avpkt, frame, got_packet_ptr);
+ if (!ret) {
+ if (*got_packet_ptr) {
if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) {
if (avpkt->pts == AV_NOPTS_VALUE)
avpkt->pts = frame->pts;
} else {
avpkt->size = 0;
}
- } else {
- /* for compatibility with encoders not supporting encode2(), we need to
- allocate a packet buffer if the user has not provided one or check
- the size otherwise */
- int fs_tmp = 0;
- int buf_size = avpkt->size;
- 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)
- return AVERROR(EINVAL);
- buf_size = nb_samples * avctx->channels *
- av_get_bits_per_sample(avctx->codec_id) / 8;
- } else {
- /* this is a guess as to the required size.
- if an encoder needs more than this, it should probably
- implement encode2() */
- buf_size = 2 * avctx->frame_size * avctx->channels *
- av_get_bytes_per_sample(avctx->sample_fmt);
- buf_size += 2*FF_MIN_BUFFER_SIZE;
- }
- }
- if ((ret = ff_alloc_packet2(avctx, avpkt, buf_size)))
- return ret;
-
- /* Encoders using AVCodec.encode() that support
- CODEC_CAP_SMALL_LAST_FRAME require avctx->frame_size to be set to
- the smaller size when encoding the last frame.
- This code can be removed once all encoders supporting
- CODEC_CAP_SMALL_LAST_FRAME use encode2() */
- if ((avctx->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) &&
- nb_samples < avctx->frame_size) {
- fs_tmp = avctx->frame_size;
- avctx->frame_size = nb_samples;
- }
-
- /* encode the frame */
- ret = avctx->codec->encode(avctx, avpkt->data, avpkt->size,
- frame ? frame->data[0] : NULL);
- if (ret >= 0) {
- if (!ret) {
- /* no output. if the packet data was allocated by libavcodec,
- free it */
- if (!user_pkt.data && avpkt->data != avctx->internal->byte_buffer)
- av_freep(&avpkt->data);
- } else {
- if (avctx->coded_frame)
- 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 = ff_samples_to_time_base(avctx,
- avctx->frame_size);
- }
- }
- avpkt->size = ret;
- *got_packet_ptr = (ret > 0);
- ret = 0;
- }
-
- if (fs_tmp)
- avctx->frame_size = fs_tmp;
}
if (avpkt->data && avpkt->data == avctx->internal->byte_buffer) {
needs_realloc = 0;
avctx->frame_number++;
}
- if (ret < 0 || !*got_packet_ptr)
+ if (ret < 0 || !*got_packet_ptr) {
av_free_packet(avpkt);
+ av_init_packet(avpkt);
+ return ret;
+ }
/* 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
here to simplify things */
avpkt->flags |= AV_PKT_FLAG_KEY;
+ if (padded_frame) {
+ av_freep(&padded_frame->data[0]);
+ if (padded_frame->extended_data != padded_frame->data)
+ av_freep(&padded_frame->extended_data);
+ av_freep(&padded_frame);
+ }
+
return ret;
}
// copy to ensure we do not change avpkt
AVPacket tmp = *avpkt;
+ if (avctx->codec->type != AVMEDIA_TYPE_VIDEO) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid media type for video\n");
+ return AVERROR(EINVAL);
+ }
+
*got_picture_ptr= 0;
if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
return -1;
int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
AVFrame *frame,
int *got_frame_ptr,
- AVPacket *avpkt)
+ const AVPacket *avpkt)
{
int ret = 0;
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
return AVERROR(EINVAL);
}
+ if (avctx->codec->type != AVMEDIA_TYPE_AUDIO) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid media type for audio\n");
+ return AVERROR(EINVAL);
+ }
if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
- av_packet_split_side_data(avpkt);
- apply_param_change(avctx, avpkt);
+ // copy to ensure we do not change avpkt
+ AVPacket tmp = *avpkt;
+ int did_split = av_packet_split_side_data(&tmp);
+ apply_param_change(avctx, &tmp);
- avctx->pkt = avpkt;
- ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
+ avctx->pkt = &tmp;
+ ret = avctx->codec->decode(avctx, frame, got_frame_ptr, &tmp);
if (ret >= 0 && *got_frame_ptr) {
avctx->frame_number++;
frame->pkt_dts = avpkt->dts;
if (frame->format == AV_SAMPLE_FMT_NONE)
frame->format = avctx->sample_fmt;
+ if (!frame->channel_layout)
+ frame->channel_layout = avctx->channel_layout;
+ if (!frame->sample_rate)
+ frame->sample_rate = avctx->sample_rate;
}
+
+ avctx->pkt = NULL;
+ if (did_split)
+ ff_packet_free_side_data(&tmp);
}
return ret;
}
{
int ret;
+ if (avctx->codec->type != AVMEDIA_TYPE_SUBTITLE) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid media type for subtitles\n");
+ return AVERROR(EINVAL);
+ }
+
avctx->pkt = avpkt;
*got_sub_ptr = 0;
avcodec_get_subtitle_defaults(sub);
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 (enc->codec)
+ p = enc->codec;
+ else
+ p = encode ? avcodec_find_encoder(enc->codec_id) :
+ avcodec_find_decoder(enc->codec_id);
if (p)
profile = av_get_profile_name(p, enc->profile);
}
ff_thread_flush(avctx);
else if(avctx->codec->flush)
avctx->codec->flush(avctx);
+
+ avctx->pts_correction_last_pts =
+ avctx->pts_correction_last_dts = INT64_MIN;
}
static void video_free_buffers(AVCodecContext *s)
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);
+ if (bps > 0 && ch > 0 && frame_bytes > 0 && ch < 32768 && bps < 32768)
+ return (frame_bytes * 8LL) / (bps * ch);
bps = avctx->bits_per_coded_sample;
/* codecs with a fixed packet duration */