* commit '354468fc12dcf93e7fb4af552e18906771913273': avplay: switch to new refcounted frames API avconv: convert to new refcounted AVFrame API Conflicts: cmdutils.c ffmpeg.c ffmpeg.h ffplay.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.0
@@ -1826,144 +1826,3 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) | |||||
} | } | ||||
return array; | return array; | ||||
} | } | ||||
static int alloc_buffer(FrameBuffer **pool, AVCodecContext *s, FrameBuffer **pbuf) | |||||
{ | |||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->pix_fmt); | |||||
FrameBuffer *buf; | |||||
int i, ret; | |||||
int pixel_size; | |||||
int h_chroma_shift, v_chroma_shift; | |||||
int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1 | |||||
int w = s->width, h = s->height; | |||||
if (!desc) | |||||
return AVERROR(EINVAL); | |||||
pixel_size = desc->comp[0].step_minus1 + 1; | |||||
buf = av_mallocz(sizeof(*buf)); | |||||
if (!buf) | |||||
return AVERROR(ENOMEM); | |||||
avcodec_align_dimensions(s, &w, &h); | |||||
if (!(s->flags & CODEC_FLAG_EMU_EDGE)) { | |||||
w += 2*edge; | |||||
h += 2*edge; | |||||
} | |||||
if ((ret = av_image_alloc(buf->base, buf->linesize, w, h, | |||||
s->pix_fmt, 32)) < 0) { | |||||
av_freep(&buf); | |||||
av_log(s, AV_LOG_ERROR, "alloc_buffer: av_image_alloc() failed\n"); | |||||
return ret; | |||||
} | |||||
avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); | |||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { | |||||
const int h_shift = i==0 ? 0 : h_chroma_shift; | |||||
const int v_shift = i==0 ? 0 : v_chroma_shift; | |||||
if ((s->flags & CODEC_FLAG_EMU_EDGE) || !buf->linesize[i] || !buf->base[i]) | |||||
buf->data[i] = buf->base[i]; | |||||
else | |||||
buf->data[i] = buf->base[i] + | |||||
FFALIGN((buf->linesize[i]*edge >> v_shift) + | |||||
(pixel_size*edge >> h_shift), 32); | |||||
} | |||||
buf->w = s->width; | |||||
buf->h = s->height; | |||||
buf->pix_fmt = s->pix_fmt; | |||||
buf->pool = pool; | |||||
*pbuf = buf; | |||||
return 0; | |||||
} | |||||
int codec_get_buffer(AVCodecContext *s, AVFrame *frame) | |||||
{ | |||||
FrameBuffer **pool = s->opaque; | |||||
FrameBuffer *buf; | |||||
int ret, i; | |||||
if(av_image_check_size(s->width, s->height, 0, s) || s->pix_fmt<0) { | |||||
av_log(s, AV_LOG_ERROR, "codec_get_buffer: image parameters invalid\n"); | |||||
return -1; | |||||
} | |||||
if (!*pool && (ret = alloc_buffer(pool, s, pool)) < 0) | |||||
return ret; | |||||
buf = *pool; | |||||
*pool = buf->next; | |||||
buf->next = NULL; | |||||
if (buf->w != s->width || buf->h != s->height || buf->pix_fmt != s->pix_fmt) { | |||||
av_freep(&buf->base[0]); | |||||
av_free(buf); | |||||
if ((ret = alloc_buffer(pool, s, &buf)) < 0) | |||||
return ret; | |||||
} | |||||
av_assert0(!buf->refcount); | |||||
buf->refcount++; | |||||
frame->opaque = buf; | |||||
frame->type = FF_BUFFER_TYPE_USER; | |||||
frame->extended_data = frame->data; | |||||
for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { | |||||
frame->base[i] = buf->base[i]; // XXX h264.c uses base though it shouldn't | |||||
frame->data[i] = buf->data[i]; | |||||
frame->linesize[i] = buf->linesize[i]; | |||||
} | |||||
return 0; | |||||
} | |||||
static void unref_buffer(FrameBuffer *buf) | |||||
{ | |||||
FrameBuffer **pool = buf->pool; | |||||
av_assert0(buf->refcount > 0); | |||||
buf->refcount--; | |||||
if (!buf->refcount) { | |||||
FrameBuffer *tmp; | |||||
for(tmp= *pool; tmp; tmp= tmp->next) | |||||
av_assert1(tmp != buf); | |||||
buf->next = *pool; | |||||
*pool = buf; | |||||
} | |||||
} | |||||
void codec_release_buffer(AVCodecContext *s, AVFrame *frame) | |||||
{ | |||||
FrameBuffer *buf = frame->opaque; | |||||
int i; | |||||
if(frame->type!=FF_BUFFER_TYPE_USER) { | |||||
avcodec_default_release_buffer(s, frame); | |||||
return; | |||||
} | |||||
for (i = 0; i < FF_ARRAY_ELEMS(frame->data); i++) | |||||
frame->data[i] = NULL; | |||||
unref_buffer(buf); | |||||
} | |||||
void filter_release_buffer(AVFilterBuffer *fb) | |||||
{ | |||||
FrameBuffer *buf = fb->priv; | |||||
av_free(fb); | |||||
unref_buffer(buf); | |||||
} | |||||
void free_buffer_pool(FrameBuffer **pool) | |||||
{ | |||||
FrameBuffer *buf = *pool; | |||||
while (buf) { | |||||
*pool = buf->next; | |||||
av_freep(&buf->base[0]); | |||||
av_free(buf); | |||||
buf = *pool; | |||||
} | |||||
} |
@@ -520,49 +520,6 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); | |||||
#define GROW_ARRAY(array, nb_elems)\ | #define GROW_ARRAY(array, nb_elems)\ | ||||
array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) | array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) | ||||
typedef struct FrameBuffer { | |||||
uint8_t *base[4]; | |||||
uint8_t *data[4]; | |||||
int linesize[4]; | |||||
int h, w; | |||||
enum AVPixelFormat pix_fmt; | |||||
int refcount; | |||||
struct FrameBuffer **pool; ///< head of the buffer pool | |||||
struct FrameBuffer *next; | |||||
} FrameBuffer; | |||||
/** | |||||
* Get a frame from the pool. This is intended to be used as a callback for | |||||
* AVCodecContext.get_buffer. | |||||
* | |||||
* @param s codec context. s->opaque must be a pointer to the head of the | |||||
* buffer pool. | |||||
* @param frame frame->opaque will be set to point to the FrameBuffer | |||||
* containing the frame data. | |||||
*/ | |||||
int codec_get_buffer(AVCodecContext *s, AVFrame *frame); | |||||
/** | |||||
* A callback to be used for AVCodecContext.release_buffer along with | |||||
* codec_get_buffer(). | |||||
*/ | |||||
void codec_release_buffer(AVCodecContext *s, AVFrame *frame); | |||||
/** | |||||
* A callback to be used for AVFilterBuffer.free. | |||||
* @param fb buffer to free. fb->priv must be a pointer to the FrameBuffer | |||||
* containing the buffer data. | |||||
*/ | |||||
void filter_release_buffer(AVFilterBuffer *fb); | |||||
/** | |||||
* Free all the buffers in the pool. This must be called after all the | |||||
* buffers have been released. | |||||
*/ | |||||
void free_buffer_pool(FrameBuffer **pool); | |||||
#define GET_PIX_FMT_NAME(pix_fmt)\ | #define GET_PIX_FMT_NAME(pix_fmt)\ | ||||
const char *name = av_get_pix_fmt_name(pix_fmt); | const char *name = av_get_pix_fmt_name(pix_fmt); | ||||
@@ -478,9 +478,9 @@ static void exit_program(void) | |||||
av_freep(&input_files[i]); | av_freep(&input_files[i]); | ||||
} | } | ||||
for (i = 0; i < nb_input_streams; i++) { | for (i = 0; i < nb_input_streams; i++) { | ||||
avcodec_free_frame(&input_streams[i]->decoded_frame); | |||||
av_frame_free(&input_streams[i]->decoded_frame); | |||||
av_frame_free(&input_streams[i]->filter_frame); | |||||
av_dict_free(&input_streams[i]->opts); | av_dict_free(&input_streams[i]->opts); | ||||
free_buffer_pool(&input_streams[i]->buffer_pool); | |||||
avsubtitle_free(&input_streams[i]->prev_sub.subtitle); | avsubtitle_free(&input_streams[i]->prev_sub.subtitle); | ||||
avcodec_free_frame(&input_streams[i]->sub2video.frame); | avcodec_free_frame(&input_streams[i]->sub2video.frame); | ||||
av_freep(&input_streams[i]->filters); | av_freep(&input_streams[i]->filters); | ||||
@@ -593,7 +593,10 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) | |||||
} | } | ||||
if (a > 0) { | if (a > 0) { | ||||
av_free_packet(pkt); | av_free_packet(pkt); | ||||
new_pkt.destruct = av_destruct_packet; | |||||
new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, | |||||
av_buffer_default_free, NULL, 0); | |||||
if (!new_pkt.buf) | |||||
exit(1); | |||||
} else if (a < 0) { | } else if (a < 0) { | ||||
av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s", | av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s", | ||||
bsfc->filter->name, pkt->stream_index, | bsfc->filter->name, pkt->stream_index, | ||||
@@ -909,36 +912,28 @@ static void do_video_out(AVFormatContext *s, | |||||
write_frame(s, &pkt, ost); | write_frame(s, &pkt, ost); | ||||
} else { | } else { | ||||
int got_packet, forced_keyframe = 0; | int got_packet, forced_keyframe = 0; | ||||
AVFrame big_picture; | |||||
double pts_time; | double pts_time; | ||||
big_picture = *in_picture; | |||||
/* better than nothing: use input picture interlaced | |||||
settings */ | |||||
big_picture.interlaced_frame = in_picture->interlaced_frame; | |||||
if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) { | |||||
if (ost->top_field_first == -1) | |||||
big_picture.top_field_first = in_picture->top_field_first; | |||||
else | |||||
big_picture.top_field_first = !!ost->top_field_first; | |||||
} | |||||
if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME) && | |||||
ost->top_field_first >= 0) | |||||
in_picture->top_field_first = !!ost->top_field_first; | |||||
if (big_picture.interlaced_frame) { | |||||
if (in_picture->interlaced_frame) { | |||||
if (enc->codec->id == AV_CODEC_ID_MJPEG) | if (enc->codec->id == AV_CODEC_ID_MJPEG) | ||||
enc->field_order = big_picture.top_field_first ? AV_FIELD_TT:AV_FIELD_BB; | |||||
enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB; | |||||
else | else | ||||
enc->field_order = big_picture.top_field_first ? AV_FIELD_TB:AV_FIELD_BT; | |||||
enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT; | |||||
} else | } else | ||||
enc->field_order = AV_FIELD_PROGRESSIVE; | enc->field_order = AV_FIELD_PROGRESSIVE; | ||||
big_picture.quality = ost->st->codec->global_quality; | |||||
in_picture->quality = ost->st->codec->global_quality; | |||||
if (!enc->me_threshold) | if (!enc->me_threshold) | ||||
big_picture.pict_type = 0; | |||||
in_picture->pict_type = 0; | |||||
pts_time = big_picture.pts != AV_NOPTS_VALUE ? | |||||
big_picture.pts * av_q2d(enc->time_base) : NAN; | |||||
pts_time = in_picture->pts != AV_NOPTS_VALUE ? | |||||
in_picture->pts * av_q2d(enc->time_base) : NAN; | |||||
if (ost->forced_kf_index < ost->forced_kf_count && | if (ost->forced_kf_index < ost->forced_kf_count && | ||||
big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) { | |||||
in_picture->pts >= ost->forced_kf_pts[ost->forced_kf_index]) { | |||||
ost->forced_kf_index++; | ost->forced_kf_index++; | ||||
forced_keyframe = 1; | forced_keyframe = 1; | ||||
} else if (ost->forced_keyframes_pexpr) { | } else if (ost->forced_keyframes_pexpr) { | ||||
@@ -965,12 +960,12 @@ static void do_video_out(AVFormatContext *s, | |||||
ost->forced_keyframes_expr_const_values[FKF_N] += 1; | ost->forced_keyframes_expr_const_values[FKF_N] += 1; | ||||
} | } | ||||
if (forced_keyframe) { | if (forced_keyframe) { | ||||
big_picture.pict_type = AV_PICTURE_TYPE_I; | |||||
in_picture->pict_type = AV_PICTURE_TYPE_I; | |||||
av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); | av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); | ||||
} | } | ||||
update_benchmark(NULL); | update_benchmark(NULL); | ||||
ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet); | |||||
ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); | |||||
update_benchmark("encode_video %d.%d", ost->file_index, ost->index); | update_benchmark("encode_video %d.%d", ost->file_index, ost->index); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); | av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); | ||||
@@ -1066,7 +1061,6 @@ static void do_video_stats(OutputStream *ost, int frame_size) | |||||
*/ | */ | ||||
static int reap_filters(void) | static int reap_filters(void) | ||||
{ | { | ||||
AVFilterBufferRef *picref; | |||||
AVFrame *filtered_frame = NULL; | AVFrame *filtered_frame = NULL; | ||||
int i; | int i; | ||||
int64_t frame_pts; | int64_t frame_pts; | ||||
@@ -1087,7 +1081,7 @@ static int reap_filters(void) | |||||
filtered_frame = ost->filtered_frame; | filtered_frame = ost->filtered_frame; | ||||
while (1) { | while (1) { | ||||
ret = av_buffersink_get_buffer_ref(ost->filter->filter, &picref, | |||||
ret = av_buffersink_get_frame_flags(ost->filter->filter, filtered_frame, | |||||
AV_BUFFERSINK_FLAG_NO_REQUEST); | AV_BUFFERSINK_FLAG_NO_REQUEST); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { | if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) { | ||||
@@ -1099,8 +1093,8 @@ static int reap_filters(void) | |||||
break; | break; | ||||
} | } | ||||
frame_pts = AV_NOPTS_VALUE; | frame_pts = AV_NOPTS_VALUE; | ||||
if (picref->pts != AV_NOPTS_VALUE) { | |||||
filtered_frame->pts = frame_pts = av_rescale_q(picref->pts, | |||||
if (filtered_frame->pts != AV_NOPTS_VALUE) { | |||||
filtered_frame->pts = frame_pts = av_rescale_q(filtered_frame->pts, | |||||
ost->filter->filter->inputs[0]->time_base, | ost->filter->filter->inputs[0]->time_base, | ||||
ost->st->codec->time_base) - | ost->st->codec->time_base) - | ||||
av_rescale_q(of->start_time, | av_rescale_q(of->start_time, | ||||
@@ -1108,7 +1102,7 @@ static int reap_filters(void) | |||||
ost->st->codec->time_base); | ost->st->codec->time_base); | ||||
if (of->start_time && filtered_frame->pts < 0) { | if (of->start_time && filtered_frame->pts < 0) { | ||||
avfilter_unref_buffer(picref); | |||||
av_frame_unref(filtered_frame); | |||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
@@ -1118,15 +1112,13 @@ static int reap_filters(void) | |||||
switch (ost->filter->filter->inputs[0]->type) { | switch (ost->filter->filter->inputs[0]->type) { | ||||
case AVMEDIA_TYPE_VIDEO: | case AVMEDIA_TYPE_VIDEO: | ||||
avfilter_copy_buf_props(filtered_frame, picref); | |||||
filtered_frame->pts = frame_pts; | filtered_frame->pts = frame_pts; | ||||
if (!ost->frame_aspect_ratio) | if (!ost->frame_aspect_ratio) | ||||
ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio; | |||||
ost->st->codec->sample_aspect_ratio = filtered_frame->sample_aspect_ratio; | |||||
do_video_out(of->ctx, ost, filtered_frame); | do_video_out(of->ctx, ost, filtered_frame); | ||||
break; | break; | ||||
case AVMEDIA_TYPE_AUDIO: | case AVMEDIA_TYPE_AUDIO: | ||||
avfilter_copy_buf_props(filtered_frame, picref); | |||||
filtered_frame->pts = frame_pts; | filtered_frame->pts = frame_pts; | ||||
if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) && | if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) && | ||||
ost->st->codec->channels != av_frame_get_channels(filtered_frame)) { | ost->st->codec->channels != av_frame_get_channels(filtered_frame)) { | ||||
@@ -1141,7 +1133,7 @@ static int reap_filters(void) | |||||
av_assert0(0); | av_assert0(0); | ||||
} | } | ||||
avfilter_unref_buffer(picref); | |||||
av_frame_unref(filtered_frame); | |||||
} | } | ||||
} | } | ||||
@@ -1482,8 +1474,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p | |||||
&& ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO | && ost->st->codec->codec_id != AV_CODEC_ID_MPEG2VIDEO | ||||
&& ost->st->codec->codec_id != AV_CODEC_ID_VC1 | && ost->st->codec->codec_id != AV_CODEC_ID_VC1 | ||||
) { | ) { | ||||
if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) | |||||
opkt.destruct = av_destruct_packet; | |||||
if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) { | |||||
opkt.buf = av_buffer_create(opkt.data, opkt.size, av_buffer_default_free, NULL, 0); | |||||
if (!opkt.buf) | |||||
exit(1); | |||||
} | |||||
} else { | } else { | ||||
opkt.data = pkt->data; | opkt.data = pkt->data; | ||||
opkt.size = pkt->size; | opkt.size = pkt->size; | ||||
@@ -1533,13 +1528,15 @@ int guess_input_channel_layout(InputStream *ist) | |||||
static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | ||||
{ | { | ||||
AVFrame *decoded_frame; | |||||
AVFrame *decoded_frame, *f; | |||||
AVCodecContext *avctx = ist->st->codec; | AVCodecContext *avctx = ist->st->codec; | ||||
int i, ret, resample_changed; | |||||
int i, ret, err = 0, resample_changed; | |||||
AVRational decoded_frame_tb; | AVRational decoded_frame_tb; | ||||
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) | if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) | ||||
return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) | |||||
return AVERROR(ENOMEM); | |||||
decoded_frame = ist->decoded_frame; | decoded_frame = ist->decoded_frame; | ||||
update_benchmark(NULL); | update_benchmark(NULL); | ||||
@@ -1554,7 +1551,11 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | |||||
if (!*got_output || ret < 0) { | if (!*got_output || ret < 0) { | ||||
if (!pkt->size) { | if (!pkt->size) { | ||||
for (i = 0; i < ist->nb_filters; i++) | for (i = 0; i < ist->nb_filters; i++) | ||||
#if 1 | |||||
av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0); | av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0); | ||||
#else | |||||
av_buffersrc_add_frame(ist->filters[i]->filter, NULL); | |||||
#endif | |||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1642,25 +1643,37 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output) | |||||
decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, | decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, | ||||
(AVRational){1, ist->st->codec->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, | (AVRational){1, ist->st->codec->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, | ||||
(AVRational){1, ist->st->codec->sample_rate}); | (AVRational){1, ist->st->codec->sample_rate}); | ||||
for (i = 0; i < ist->nb_filters; i++) | |||||
av_buffersrc_add_frame_flags(ist->filters[i]->filter, decoded_frame, | |||||
AV_BUFFERSRC_FLAG_KEEP_REF | | |||||
for (i = 0; i < ist->nb_filters; i++) { | |||||
if (i < ist->nb_filters - 1) { | |||||
f = ist->filter_frame; | |||||
err = av_frame_ref(f, decoded_frame); | |||||
if (err < 0) | |||||
break; | |||||
} else | |||||
f = decoded_frame; | |||||
err = av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, | |||||
AV_BUFFERSRC_FLAG_PUSH); | AV_BUFFERSRC_FLAG_PUSH); | ||||
if (err < 0) | |||||
break; | |||||
} | |||||
decoded_frame->pts = AV_NOPTS_VALUE; | decoded_frame->pts = AV_NOPTS_VALUE; | ||||
return ret; | |||||
av_frame_unref(ist->filter_frame); | |||||
av_frame_unref(decoded_frame); | |||||
return err < 0 ? err : ret; | |||||
} | } | ||||
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | ||||
{ | { | ||||
AVFrame *decoded_frame; | |||||
AVFrame *decoded_frame, *f; | |||||
void *buffer_to_free = NULL; | void *buffer_to_free = NULL; | ||||
int i, ret = 0, resample_changed; | |||||
int i, ret = 0, err = 0, resample_changed; | |||||
int64_t best_effort_timestamp; | int64_t best_effort_timestamp; | ||||
AVRational *frame_sample_aspect; | AVRational *frame_sample_aspect; | ||||
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame())) | |||||
if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) | |||||
return AVERROR(ENOMEM); | |||||
if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) | |||||
return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
decoded_frame = ist->decoded_frame; | decoded_frame = ist->decoded_frame; | ||||
pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); | pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); | ||||
@@ -1672,7 +1685,11 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | |||||
if (!*got_output || ret < 0) { | if (!*got_output || ret < 0) { | ||||
if (!pkt->size) { | if (!pkt->size) { | ||||
for (i = 0; i < ist->nb_filters; i++) | for (i = 0; i < ist->nb_filters; i++) | ||||
#if 1 | |||||
av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0); | av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0); | ||||
#else | |||||
av_buffersrc_add_frame(ist->filters[i]->filter, NULL); | |||||
#endif | |||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
@@ -1735,27 +1752,15 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | |||||
if (!frame_sample_aspect->num) | if (!frame_sample_aspect->num) | ||||
*frame_sample_aspect = ist->st->sample_aspect_ratio; | *frame_sample_aspect = ist->st->sample_aspect_ratio; | ||||
if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) { | |||||
FrameBuffer *buf = decoded_frame->opaque; | |||||
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays( | |||||
decoded_frame->data, decoded_frame->linesize, | |||||
AV_PERM_READ | AV_PERM_PRESERVE, | |||||
ist->st->codec->width, ist->st->codec->height, | |||||
ist->st->codec->pix_fmt); | |||||
avfilter_copy_frame_props(fb, decoded_frame); | |||||
fb->buf->priv = buf; | |||||
fb->buf->free = filter_release_buffer; | |||||
av_assert0(buf->refcount>0); | |||||
buf->refcount++; | |||||
av_buffersrc_add_ref(ist->filters[i]->filter, fb, | |||||
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT | | |||||
AV_BUFFERSRC_FLAG_NO_COPY | | |||||
AV_BUFFERSRC_FLAG_PUSH); | |||||
if (i < ist->nb_filters - 1) { | |||||
f = ist->filter_frame; | |||||
err = av_frame_ref(f, decoded_frame); | |||||
if (err < 0) | |||||
break; | |||||
} else | } else | ||||
if(av_buffersrc_add_frame_flags(ist->filters[i]->filter, decoded_frame, | |||||
AV_BUFFERSRC_FLAG_KEEP_REF | | |||||
f = decoded_frame; | |||||
if(av_buffersrc_add_frame_flags(ist->filters[i]->filter, f, | |||||
AV_BUFFERSRC_FLAG_PUSH)<0) { | AV_BUFFERSRC_FLAG_PUSH)<0) { | ||||
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n"); | av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n"); | ||||
exit(1); | exit(1); | ||||
@@ -1763,8 +1768,10 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output) | |||||
} | } | ||||
av_frame_unref(ist->filter_frame); | |||||
av_frame_unref(decoded_frame); | |||||
av_free(buffer_to_free); | av_free(buffer_to_free); | ||||
return ret; | |||||
return err < 0 ? err : ret; | |||||
} | } | ||||
static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) | static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) | ||||
@@ -1980,12 +1987,7 @@ static int init_input_stream(int ist_index, char *error, int error_len) | |||||
return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
} | } | ||||
ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) && !(FF_API_DEINTERLACE && do_deinterlace); | |||||
if (codec->type == AVMEDIA_TYPE_VIDEO && ist->dr1) { | |||||
ist->st->codec->get_buffer = codec_get_buffer; | |||||
ist->st->codec->release_buffer = codec_release_buffer; | |||||
ist->st->codec->opaque = &ist->buffer_pool; | |||||
} | |||||
av_opt_set_int(ist->st->codec, "refcounted_frames", 1, 0); | |||||
if (!av_dict_get(ist->opts, "threads", NULL, 0)) | if (!av_dict_get(ist->opts, "threads", NULL, 0)) | ||||
av_dict_set(&ist->opts, "threads", "auto", 0); | av_dict_set(&ist->opts, "threads", "auto", 0); | ||||
@@ -216,6 +216,7 @@ typedef struct InputStream { | |||||
int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */ | int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */ | ||||
AVCodec *dec; | AVCodec *dec; | ||||
AVFrame *decoded_frame; | AVFrame *decoded_frame; | ||||
AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ | |||||
int64_t start; /* time when read started */ | int64_t start; /* time when read started */ | ||||
/* predicted dts of the next packet read for this stream or (when there are | /* predicted dts of the next packet read for this stream or (when there are | ||||
@@ -261,8 +262,6 @@ typedef struct InputStream { | |||||
int w, h; | int w, h; | ||||
} sub2video; | } sub2video; | ||||
/* a pool of free buffers for decoded data */ | |||||
FrameBuffer *buffer_pool; | |||||
int dr1; | int dr1; | ||||
/* decoded data from this stream goes into all those filters | /* decoded data from this stream goes into all those filters | ||||
@@ -121,14 +121,11 @@ typedef struct VideoPicture { | |||||
int64_t pos; // byte position in file | int64_t pos; // byte position in file | ||||
SDL_Overlay *bmp; | SDL_Overlay *bmp; | ||||
int width, height; /* source height & width */ | int width, height; /* source height & width */ | ||||
AVRational sample_aspect_ratio; | |||||
int allocated; | int allocated; | ||||
int reallocate; | int reallocate; | ||||
int serial; | int serial; | ||||
#if CONFIG_AVFILTER | |||||
AVFilterBufferRef *picref; | |||||
#endif | |||||
AVRational sar; | |||||
} VideoPicture; | } VideoPicture; | ||||
typedef struct SubPicture { | typedef struct SubPicture { | ||||
@@ -256,8 +253,6 @@ typedef struct VideoState { | |||||
#if CONFIG_AVFILTER | #if CONFIG_AVFILTER | ||||
AVFilterContext *in_video_filter; // the first filter in the video chain | AVFilterContext *in_video_filter; // the first filter in the video chain | ||||
AVFilterContext *out_video_filter; // the last filter in the video chain | AVFilterContext *out_video_filter; // the last filter in the video chain | ||||
int use_dr1; | |||||
FrameBuffer *buffer_pool; | |||||
#endif | #endif | ||||
int last_video_stream, last_audio_stream, last_subtitle_stream; | int last_video_stream, last_audio_stream, last_subtitle_stream; | ||||
@@ -753,10 +748,10 @@ static void calculate_display_rect(SDL_Rect *rect, int scr_xleft, int scr_ytop, | |||||
float aspect_ratio; | float aspect_ratio; | ||||
int width, height, x, y; | int width, height, x, y; | ||||
if (vp->sample_aspect_ratio.num == 0) | |||||
if (vp->sar.num == 0) | |||||
aspect_ratio = 0; | aspect_ratio = 0; | ||||
else | else | ||||
aspect_ratio = av_q2d(vp->sample_aspect_ratio); | |||||
aspect_ratio = av_q2d(vp->sar); | |||||
if (aspect_ratio <= 0.0) | if (aspect_ratio <= 0.0) | ||||
aspect_ratio = 1.0; | aspect_ratio = 1.0; | ||||
@@ -982,9 +977,6 @@ static void stream_close(VideoState *is) | |||||
/* free all pictures */ | /* free all pictures */ | ||||
for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) { | for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) { | ||||
vp = &is->pictq[i]; | vp = &is->pictq[i]; | ||||
#if CONFIG_AVFILTER | |||||
avfilter_unref_bufferp(&vp->picref); | |||||
#endif | |||||
if (vp->bmp) { | if (vp->bmp) { | ||||
SDL_FreeYUVOverlay(vp->bmp); | SDL_FreeYUVOverlay(vp->bmp); | ||||
vp->bmp = NULL; | vp->bmp = NULL; | ||||
@@ -1477,10 +1469,6 @@ static void alloc_picture(VideoState *is) | |||||
if (vp->bmp) | if (vp->bmp) | ||||
SDL_FreeYUVOverlay(vp->bmp); | SDL_FreeYUVOverlay(vp->bmp); | ||||
#if CONFIG_AVFILTER | |||||
avfilter_unref_bufferp(&vp->picref); | |||||
#endif | |||||
video_open(is, 0, vp); | video_open(is, 0, vp); | ||||
vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height, | vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height, | ||||
@@ -1544,9 +1532,9 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t | |||||
vp = &is->pictq[is->pictq_windex]; | vp = &is->pictq[is->pictq_windex]; | ||||
#if CONFIG_AVFILTER | #if CONFIG_AVFILTER | ||||
vp->sample_aspect_ratio = ((AVFilterBufferRef *)src_frame->opaque)->video->sample_aspect_ratio; | |||||
vp->sar = src_frame->sample_aspect_ratio; | |||||
#else | #else | ||||
vp->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, src_frame); | |||||
vp->sar = av_guess_sample_aspect_ratio(is->ic, is->video_st, src_frame); | |||||
#endif | #endif | ||||
/* alloc or resize hardware picture buffer */ | /* alloc or resize hardware picture buffer */ | ||||
@@ -1586,10 +1574,6 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t | |||||
/* if the frame is not skipped, then display it */ | /* if the frame is not skipped, then display it */ | ||||
if (vp->bmp) { | if (vp->bmp) { | ||||
AVPicture pict = { { 0 } }; | AVPicture pict = { { 0 } }; | ||||
#if CONFIG_AVFILTER | |||||
avfilter_unref_bufferp(&vp->picref); | |||||
vp->picref = src_frame->opaque; | |||||
#endif | |||||
/* get a pointer on the bitmap */ | /* get a pointer on the bitmap */ | ||||
SDL_LockYUVOverlay (vp->bmp); | SDL_LockYUVOverlay (vp->bmp); | ||||
@@ -1658,7 +1642,6 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke | |||||
is->frame_timer = (double)av_gettime() / 1000000.0; | is->frame_timer = (double)av_gettime() / 1000000.0; | ||||
is->frame_last_dropped_pts = AV_NOPTS_VALUE; | is->frame_last_dropped_pts = AV_NOPTS_VALUE; | ||||
SDL_UnlockMutex(is->pictq_mutex); | SDL_UnlockMutex(is->pictq_mutex); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -1804,7 +1787,7 @@ static int video_thread(void *arg) | |||||
{ | { | ||||
AVPacket pkt = { 0 }; | AVPacket pkt = { 0 }; | ||||
VideoState *is = arg; | VideoState *is = arg; | ||||
AVFrame *frame = avcodec_alloc_frame(); | |||||
AVFrame *frame = av_frame_alloc(); | |||||
int64_t pts_int = AV_NOPTS_VALUE, pos = -1; | int64_t pts_int = AV_NOPTS_VALUE, pos = -1; | ||||
double pts; | double pts; | ||||
int ret; | int ret; | ||||
@@ -1818,18 +1801,10 @@ static int video_thread(void *arg) | |||||
int last_h = 0; | int last_h = 0; | ||||
enum AVPixelFormat last_format = -2; | enum AVPixelFormat last_format = -2; | ||||
int last_serial = -1; | int last_serial = -1; | ||||
if (codec->codec->capabilities & CODEC_CAP_DR1) { | |||||
is->use_dr1 = 1; | |||||
codec->get_buffer = codec_get_buffer; | |||||
codec->release_buffer = codec_release_buffer; | |||||
codec->opaque = &is->buffer_pool; | |||||
} | |||||
#endif | #endif | ||||
for (;;) { | for (;;) { | ||||
#if CONFIG_AVFILTER | #if CONFIG_AVFILTER | ||||
AVFilterBufferRef *picref; | |||||
AVRational tb; | AVRational tb; | ||||
#endif | #endif | ||||
while (is->paused && !is->videoq.abort_request) | while (is->paused && !is->videoq.abort_request) | ||||
@@ -1876,30 +1851,17 @@ static int video_thread(void *arg) | |||||
frame->pts = pts_int; | frame->pts = pts_int; | ||||
frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame); | frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame); | ||||
if (is->use_dr1 && frame->opaque) { | |||||
FrameBuffer *buf = frame->opaque; | |||||
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays( | |||||
frame->data, frame->linesize, | |||||
AV_PERM_READ | AV_PERM_PRESERVE, | |||||
frame->width, frame->height, | |||||
frame->format); | |||||
avfilter_copy_frame_props(fb, frame); | |||||
fb->buf->priv = buf; | |||||
fb->buf->free = filter_release_buffer; | |||||
buf->refcount++; | |||||
av_buffersrc_add_ref(filt_in, fb, AV_BUFFERSRC_FLAG_NO_COPY); | |||||
} else | |||||
av_buffersrc_write_frame(filt_in, frame); | |||||
ret = av_buffersrc_add_frame(filt_in, frame); | |||||
if (ret < 0) | |||||
goto the_end; | |||||
av_frame_unref(frame); | |||||
avcodec_get_frame_defaults(frame); | |||||
av_free_packet(&pkt); | av_free_packet(&pkt); | ||||
while (ret >= 0) { | while (ret >= 0) { | ||||
is->frame_last_returned_time = av_gettime() / 1000000.0; | is->frame_last_returned_time = av_gettime() / 1000000.0; | ||||
ret = av_buffersink_get_buffer_ref(filt_out, &picref, 0); | |||||
ret = av_buffersink_get_frame_flags(filt_out, frame, 0); | |||||
if (ret < 0) { | if (ret < 0) { | ||||
ret = 0; | ret = 0; | ||||
break; | break; | ||||
@@ -1909,13 +1871,9 @@ static int video_thread(void *arg) | |||||
if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) | if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) | ||||
is->frame_last_filter_delay = 0; | is->frame_last_filter_delay = 0; | ||||
avfilter_copy_buf_props(frame, picref); | |||||
pts_int = picref->pts; | |||||
pts_int = frame->pts; | |||||
tb = filt_out->inputs[0]->time_base; | tb = filt_out->inputs[0]->time_base; | ||||
pos = picref->pos; | |||||
frame->opaque = picref; | |||||
pos = av_frame_get_pkt_pos(frame); | |||||
if (av_cmp_q(tb, is->video_st->time_base)) { | if (av_cmp_q(tb, is->video_st->time_base)) { | ||||
av_unused int64_t pts1 = pts_int; | av_unused int64_t pts1 = pts_int; | ||||
pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base); | pts_int = av_rescale_q(pts_int, tb, is->video_st->time_base); | ||||
@@ -1926,10 +1884,12 @@ static int video_thread(void *arg) | |||||
} | } | ||||
pts = pts_int * av_q2d(is->video_st->time_base); | pts = pts_int * av_q2d(is->video_st->time_base); | ||||
ret = queue_picture(is, frame, pts, pos, serial); | ret = queue_picture(is, frame, pts, pos, serial); | ||||
av_frame_unref(frame); | |||||
} | } | ||||
#else | #else | ||||
pts = pts_int * av_q2d(is->video_st->time_base); | pts = pts_int * av_q2d(is->video_st->time_base); | ||||
ret = queue_picture(is, frame, pts, pkt.pos, serial); | ret = queue_picture(is, frame, pts, pkt.pos, serial); | ||||
av_frame_unref(frame); | |||||
#endif | #endif | ||||
if (ret < 0) | if (ret < 0) | ||||
@@ -1941,7 +1901,7 @@ static int video_thread(void *arg) | |||||
avfilter_graph_free(&graph); | avfilter_graph_free(&graph); | ||||
#endif | #endif | ||||
av_free_packet(&pkt); | av_free_packet(&pkt); | ||||
avcodec_free_frame(&frame); | |||||
av_frame_free(&frame); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -2384,6 +2344,8 @@ static int stream_component_open(VideoState *is, int stream_index) | |||||
opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec); | opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec); | ||||
if (!av_dict_get(opts, "threads", NULL, 0)) | if (!av_dict_get(opts, "threads", NULL, 0)) | ||||
av_dict_set(&opts, "threads", "auto", 0); | av_dict_set(&opts, "threads", "auto", 0); | ||||
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) | |||||
av_dict_set(&opts, "refcounted_frames", "1", 0); | |||||
if (avcodec_open2(avctx, codec, &opts) < 0) | if (avcodec_open2(avctx, codec, &opts) < 0) | ||||
return -1; | return -1; | ||||
if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { | if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { | ||||
@@ -2504,9 +2466,6 @@ static void stream_component_close(VideoState *is, int stream_index) | |||||
ic->streams[stream_index]->discard = AVDISCARD_ALL; | ic->streams[stream_index]->discard = AVDISCARD_ALL; | ||||
avcodec_close(avctx); | avcodec_close(avctx); | ||||
#if CONFIG_AVFILTER | |||||
free_buffer_pool(&is->buffer_pool); | |||||
#endif | |||||
switch (avctx->codec_type) { | switch (avctx->codec_type) { | ||||
case AVMEDIA_TYPE_AUDIO: | case AVMEDIA_TYPE_AUDIO: | ||||
is->audio_st = NULL; | is->audio_st = NULL; | ||||