Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/CMakeLists.txt6
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c161
-rw-r--r--source/blender/imbuf/intern/indexer.c241
-rw-r--r--source/blender/imbuf/intern/util.c16
5 files changed, 224 insertions, 202 deletions
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index 7ce795280a3..be0e364c85f 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -166,12 +166,6 @@ if(WITH_CODEC_FFMPEG)
${OPENJPEG_LIBRARIES}
)
add_definitions(-DWITH_FFMPEG)
-
- remove_strict_c_flags_file(
- intern/anim_movie.c
- intern/indexer.c
- intern/util.c
- )
endif()
if(WITH_IMAGE_DDS)
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 1239d3881de..7d7864306a1 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -135,7 +135,7 @@ struct anim {
struct ImBuf *last_frame;
int64_t last_pts;
int64_t next_pts;
- AVPacket next_packet;
+ AVPacket *next_packet;
#endif
char index_dir[768];
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 432b62d172a..cdf6ca5c181 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -79,6 +79,7 @@
# include <libavcodec/avcodec.h>
# include <libavformat/avformat.h>
+# include <libavutil/imgutils.h>
# include <libavutil/rational.h>
# include <libswscale/swscale.h>
@@ -519,12 +520,10 @@ static int startffmpeg(struct anim *anim)
double frs_den;
int streamcount;
-# ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
/* The following for color space determination */
int srcRange, dstRange, brightness, contrast, saturation;
int *table;
const int *inv_table;
-# endif
if (anim == NULL) {
return (-1);
@@ -547,7 +546,7 @@ static int startffmpeg(struct anim *anim)
video_stream_index = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
- if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (streamcount > 0) {
streamcount--;
continue;
@@ -563,16 +562,17 @@ static int startffmpeg(struct anim *anim)
}
video_stream = pFormatCtx->streams[video_stream_index];
- pCodecCtx = video_stream->codec;
/* Find the decoder for the video stream */
- pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
+ pCodec = avcodec_find_decoder(video_stream->codecpar->codec_id);
if (pCodec == NULL) {
avformat_close_input(&pFormatCtx);
return -1;
}
- pCodecCtx->workaround_bugs = 1;
+ pCodecCtx = avcodec_alloc_context3(NULL);
+ avcodec_parameters_to_context(pCodecCtx, video_stream->codecpar);
+ pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
if (pCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
pCodecCtx->thread_count = 0;
@@ -593,7 +593,7 @@ static int startffmpeg(struct anim *anim)
return -1;
}
if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) {
- avcodec_close(anim->pCodecCtx);
+ avcodec_free_context(&anim->pCodecCtx);
avformat_close_input(&pFormatCtx);
return -1;
}
@@ -639,7 +639,7 @@ static int startffmpeg(struct anim *anim)
anim->params = 0;
anim->x = pCodecCtx->width;
- anim->y = av_get_cropped_height_from_codec(pCodecCtx);
+ anim->y = pCodecCtx->height;
anim->pFormatCtx = pFormatCtx;
anim->pCodecCtx = pCodecCtx;
@@ -654,7 +654,8 @@ static int startffmpeg(struct anim *anim)
anim->last_frame = 0;
anim->last_pts = -1;
anim->next_pts = -1;
- anim->next_packet.stream_index = -1;
+ anim->next_packet = av_packet_alloc();
+ anim->next_packet->stream_index = -1;
anim->pFrame = av_frame_alloc();
anim->pFrameComplete = false;
@@ -668,8 +669,9 @@ static int startffmpeg(struct anim *anim)
if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) {
fprintf(stderr, "Could not allocate frame data.\n");
- avcodec_close(anim->pCodecCtx);
+ avcodec_free_context(&anim->pCodecCtx);
avformat_close_input(&anim->pFormatCtx);
+ av_packet_free(&anim->next_packet);
av_frame_free(&anim->pFrameRGB);
av_frame_free(&anim->pFrameDeinterlaced);
av_frame_free(&anim->pFrame);
@@ -678,10 +680,11 @@ static int startffmpeg(struct anim *anim)
}
}
- if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) != anim->x * anim->y * 4) {
+ if (av_image_get_buffer_size(AV_PIX_FMT_RGBA, anim->x, anim->y, 1) != anim->x * anim->y * 4) {
fprintf(stderr, "ffmpeg has changed alloc scheme ... ARGHHH!\n");
- avcodec_close(anim->pCodecCtx);
+ avcodec_free_context(&anim->pCodecCtx);
avformat_close_input(&anim->pFormatCtx);
+ av_packet_free(&anim->next_packet);
av_frame_free(&anim->pFrameRGB);
av_frame_free(&anim->pFrameDeinterlaced);
av_frame_free(&anim->pFrame);
@@ -690,14 +693,17 @@ static int startffmpeg(struct anim *anim)
}
if (anim->ib_flags & IB_animdeinterlace) {
- avpicture_fill((AVPicture *)anim->pFrameDeinterlaced,
- MEM_callocN(avpicture_get_size(anim->pCodecCtx->pix_fmt,
- anim->pCodecCtx->width,
- anim->pCodecCtx->height),
- "ffmpeg deinterlace"),
- anim->pCodecCtx->pix_fmt,
- anim->pCodecCtx->width,
- anim->pCodecCtx->height);
+ av_image_fill_arrays(anim->pFrameDeinterlaced->data,
+ anim->pFrameDeinterlaced->linesize,
+ MEM_callocN(av_image_get_buffer_size(anim->pCodecCtx->pix_fmt,
+ anim->pCodecCtx->width,
+ anim->pCodecCtx->height,
+ 1),
+ "ffmpeg deinterlace"),
+ anim->pCodecCtx->pix_fmt,
+ anim->pCodecCtx->width,
+ anim->pCodecCtx->height,
+ 1);
}
if (pCodecCtx->has_b_frames) {
@@ -720,8 +726,9 @@ static int startffmpeg(struct anim *anim)
if (!anim->img_convert_ctx) {
fprintf(stderr, "Can't transform color space??? Bailing out...\n");
- avcodec_close(anim->pCodecCtx);
+ avcodec_free_context(&anim->pCodecCtx);
avformat_close_input(&anim->pFormatCtx);
+ av_packet_free(&anim->next_packet);
av_frame_free(&anim->pFrameRGB);
av_frame_free(&anim->pFrameDeinterlaced);
av_frame_free(&anim->pFrame);
@@ -729,7 +736,6 @@ static int startffmpeg(struct anim *anim)
return -1;
}
-# ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
/* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */
if (!sws_getColorspaceDetails(anim->img_convert_ctx,
(int **)&inv_table,
@@ -756,7 +762,6 @@ static int startffmpeg(struct anim *anim)
else {
fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n");
}
-# endif
return 0;
}
@@ -795,11 +800,11 @@ static void ffmpeg_postprocess(struct anim *anim)
input->data[3]);
if (anim->ib_flags & IB_animdeinterlace) {
- if (avpicture_deinterlace((AVPicture *)anim->pFrameDeinterlaced,
- (const AVPicture *)anim->pFrame,
- anim->pCodecCtx->pix_fmt,
- anim->pCodecCtx->width,
- anim->pCodecCtx->height) < 0) {
+ if (av_image_deinterlace(anim->pFrameDeinterlaced,
+ anim->pFrame,
+ anim->pCodecCtx->pix_fmt,
+ anim->pCodecCtx->width,
+ anim->pCodecCtx->height) < 0) {
filter_y = true;
}
else {
@@ -808,11 +813,13 @@ static void ffmpeg_postprocess(struct anim *anim)
}
if (!need_aligned_ffmpeg_buffer(anim)) {
- avpicture_fill((AVPicture *)anim->pFrameRGB,
- (unsigned char *)ibuf->rect,
- AV_PIX_FMT_RGBA,
- anim->x,
- anim->y);
+ av_image_fill_arrays(anim->pFrameRGB->data,
+ anim->pFrameRGB->linesize,
+ (unsigned char *)ibuf->rect,
+ AV_PIX_FMT_RGBA,
+ anim->x,
+ anim->y,
+ 1);
}
# if defined(__x86_64__) || defined(_M_X64)
@@ -903,82 +910,70 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n");
- if (anim->next_packet.stream_index == anim->videoStream) {
- av_free_packet(&anim->next_packet);
- anim->next_packet.stream_index = -1;
+ if (anim->next_packet->stream_index == anim->videoStream) {
+ av_packet_unref(anim->next_packet);
+ anim->next_packet->stream_index = -1;
}
- while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) {
+ while ((rval = av_read_frame(anim->pFormatCtx, anim->next_packet)) >= 0) {
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
"%sREAD: strID=%d (VID: %d) dts=%" PRId64 " pts=%" PRId64 " %s\n",
- (anim->next_packet.stream_index == anim->videoStream) ? "->" : " ",
- anim->next_packet.stream_index,
+ (anim->next_packet->stream_index == anim->videoStream) ? "->" : " ",
+ anim->next_packet->stream_index,
anim->videoStream,
- (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet.dts,
- (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet.pts,
- (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
- if (anim->next_packet.stream_index == anim->videoStream) {
+ (anim->next_packet->dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->dts,
+ (anim->next_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->pts,
+ (anim->next_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
+ if (anim->next_packet->stream_index == anim->videoStream) {
anim->pFrameComplete = 0;
- avcodec_decode_video2(
- anim->pCodecCtx, anim->pFrame, &anim->pFrameComplete, &anim->next_packet);
+ avcodec_send_packet(anim->pCodecCtx, anim->next_packet);
+ anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
if (anim->pFrameComplete) {
anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- " FRAME DONE: next_pts=%" PRId64 " pkt_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
+ " FRAME DONE: next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
(anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pkt_pts,
(int64_t)anim->next_pts);
break;
}
}
- av_free_packet(&anim->next_packet);
- anim->next_packet.stream_index = -1;
+ av_packet_unref(anim->next_packet);
+ anim->next_packet->stream_index = -1;
}
if (rval == AVERROR_EOF) {
- /* this sets size and data fields to zero,
- * which is necessary to decode the remaining data
- * in the decoder engine after EOF. It also prevents a memory
- * leak, since av_read_frame spills out a full size packet even
- * on EOF... (and: it's safe to call on NULL packets) */
-
- av_free_packet(&anim->next_packet);
-
- anim->next_packet.size = 0;
- anim->next_packet.data = 0;
-
+ /* Flush any remaining frames out of the decoder. */
anim->pFrameComplete = 0;
- avcodec_decode_video2(
- anim->pCodecCtx, anim->pFrame, &anim->pFrameComplete, &anim->next_packet);
+ avcodec_send_packet(anim->pCodecCtx, NULL);
+ anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0;
if (anim->pFrameComplete) {
anim->next_pts = av_get_pts_from_frame(anim->pFormatCtx, anim->pFrame);
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- " FRAME DONE (after EOF): next_pts=%" PRId64 " pkt_pts=%" PRId64
- ", guessed_pts=%" PRId64 "\n",
+ " FRAME DONE (after EOF): next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
(anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pkt_pts,
(int64_t)anim->next_pts);
rval = 0;
}
}
if (rval < 0) {
- anim->next_packet.stream_index = -1;
+ av_packet_unref(anim->next_packet);
+ anim->next_packet->stream_index = -1;
av_log(anim->pFormatCtx,
AV_LOG_ERROR,
" DECODE READ FAILED: av_read_frame() "
- "returned error: %d\n",
- rval);
+ "returned error: %s\n",
+ av_err2str(rval));
}
return (rval >= 0);
@@ -1154,7 +1149,7 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim, int64_t requested_p
/* Read first video stream packet. */
AVPacket read_packet = {0};
while (av_read_frame(anim->pFormatCtx, &read_packet) >= 0) {
- if (anim->next_packet.stream_index == anim->videoStream) {
+ if (anim->next_packet->stream_index == anim->videoStream) {
break;
}
}
@@ -1246,9 +1241,9 @@ static void ffmpeg_seek_and_decode(struct anim *anim, int position, struct anim_
anim->next_pts = -1;
- if (anim->next_packet.stream_index == anim->videoStream) {
- av_free_packet(&anim->next_packet);
- anim->next_packet.stream_index = -1;
+ if (anim->next_packet->stream_index == anim->videoStream) {
+ av_packet_unref(anim->next_packet);
+ anim->next_packet->stream_index = -1;
}
/* memset(anim->pFrame, ...) ?? */
@@ -1351,32 +1346,30 @@ static void free_anim_ffmpeg(struct anim *anim)
}
if (anim->pCodecCtx) {
- avcodec_close(anim->pCodecCtx);
+ avcodec_free_context(&anim->pCodecCtx);
avformat_close_input(&anim->pFormatCtx);
+ av_packet_free(&anim->next_packet);
- /* Special case here: pFrame could share pointers with codec,
- * so in order to avoid double-free we don't use av_frame_free()
- * to free the frame.
- *
- * Could it be a bug in FFmpeg?
- */
- av_free(anim->pFrame);
+ av_frame_free(&anim->pFrame);
if (!need_aligned_ffmpeg_buffer(anim)) {
/* If there's no need for own aligned buffer it means that FFmpeg's
* frame shares the same buffer as temporary ImBuf. In this case we
* should not free the buffer when freeing the FFmpeg buffer.
*/
- avpicture_fill((AVPicture *)anim->pFrameRGB, NULL, AV_PIX_FMT_RGBA, anim->x, anim->y);
+ av_image_fill_arrays(anim->pFrameRGB->data,
+ anim->pFrameRGB->linesize,
+ NULL,
+ AV_PIX_FMT_RGBA,
+ anim->x,
+ anim->y,
+ 1);
}
av_frame_free(&anim->pFrameRGB);
av_frame_free(&anim->pFrameDeinterlaced);
sws_freeContext(anim->img_convert_ctx);
IMB_freeImBuf(anim->last_frame);
- if (anim->next_packet.stream_index != -1) {
- av_free_packet(&anim->next_packet);
- }
}
anim->duration_in_frames = 0;
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index ef9f6d861a3..11ce77e3091 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -48,6 +48,7 @@
#ifdef WITH_FFMPEG
# include "ffmpeg_compat.h"
+# include <libavutil/imgutils.h>
#endif
static const char magic[] = "BlenMIdx";
@@ -488,14 +489,14 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->of = avformat_alloc_context();
rv->of->oformat = av_guess_format("avi", NULL, NULL);
- BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename));
+ rv->of->url = av_strdup(fname);
- fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);
+ fprintf(stderr, "Starting work on proxy: %s\n", rv->of->url);
rv->st = avformat_new_stream(rv->of, NULL);
rv->st->id = 0;
- rv->c = rv->st->codec;
+ rv->c = avcodec_alloc_context3(NULL);
rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
rv->c->codec_id = AV_CODEC_ID_H264;
rv->c->width = width;
@@ -513,7 +514,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
fprintf(stderr,
"No ffmpeg encoder available? "
"Proxy not built!\n");
- av_free(rv->of);
+ avcodec_free_context(&rv->c);
+ avformat_free_context(rv->of);
+ MEM_freeN(rv);
return NULL;
}
@@ -524,7 +527,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->c->pix_fmt = AV_PIX_FMT_YUVJ420P;
}
- rv->c->sample_aspect_ratio = rv->st->sample_aspect_ratio = st->codec->sample_aspect_ratio;
+ rv->c->sample_aspect_ratio = rv->st->sample_aspect_ratio = st->sample_aspect_ratio;
rv->c->time_base.den = 25;
rv->c->time_base.num = 1;
@@ -557,34 +560,54 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
}
if (rv->of->flags & AVFMT_GLOBALHEADER) {
- rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ rv->c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
- if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) {
+ avcodec_parameters_from_context(rv->st->codecpar, rv->c);
+
+ int ret = avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE);
+
+ if (ret < 0) {
fprintf(stderr,
- "Couldn't open outputfile! "
- "Proxy not built!\n");
- av_free(rv->of);
- return 0;
+ "Couldn't open IO: %s\n"
+ "Proxy not built!\n",
+ av_err2str(ret));
+ avcodec_free_context(&rv->c);
+ avformat_free_context(rv->of);
+ MEM_freeN(rv);
+ return NULL;
}
- avcodec_open2(rv->c, rv->codec, &codec_opts);
+ ret = avcodec_open2(rv->c, rv->codec, &codec_opts);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Couldn't open codec: %s\n"
+ "Proxy not built!\n",
+ av_err2str(ret));
+ avcodec_free_context(&rv->c);
+ avformat_free_context(rv->of);
+ MEM_freeN(rv);
+ return NULL;
+ }
- rv->orig_height = av_get_cropped_height_from_codec(st->codec);
+ rv->orig_height = st->codecpar->height;
- if (st->codec->width != width || st->codec->height != height ||
- st->codec->pix_fmt != rv->c->pix_fmt) {
+ if (st->codecpar->width != width || st->codecpar->height != height ||
+ st->codecpar->format != rv->c->pix_fmt) {
rv->frame = av_frame_alloc();
- avpicture_fill((AVPicture *)rv->frame,
- MEM_mallocN(avpicture_get_size(rv->c->pix_fmt, round_up(width, 16), height),
- "alloc proxy output frame"),
- rv->c->pix_fmt,
- round_up(width, 16),
- height);
-
- rv->sws_ctx = sws_getContext(st->codec->width,
+ av_image_fill_arrays(
+ rv->frame->data,
+ rv->frame->linesize,
+ MEM_mallocN(av_image_get_buffer_size(rv->c->pix_fmt, round_up(width, 16), height, 1),
+ "alloc proxy output frame"),
+ rv->c->pix_fmt,
+ round_up(width, 16),
+ height,
+ 1);
+
+ rv->sws_ctx = sws_getContext(st->codecpar->width,
rv->orig_height,
- st->codec->pix_fmt,
+ st->codecpar->format,
width,
height,
rv->c->pix_fmt,
@@ -594,26 +617,30 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
NULL);
}
- if (avformat_write_header(rv->of, NULL) < 0) {
+ ret = avformat_write_header(rv->of, NULL);
+ if (ret < 0) {
fprintf(stderr,
- "Couldn't set output parameters? "
- "Proxy not built!\n");
- av_free(rv->of);
- return 0;
+ "Couldn't write header: %s\n"
+ "Proxy not built!\n",
+ av_err2str(ret));
+
+ if (rv->frame) {
+ av_frame_free(&rv->frame);
+ }
+
+ avcodec_free_context(&rv->c);
+ avformat_free_context(rv->of);
+ MEM_freeN(rv);
+ return NULL;
}
return rv;
}
-static int add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *frame)
+static void add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *frame)
{
- AVPacket packet = {0};
- int ret, got_output;
-
- av_init_packet(&packet);
-
if (!ctx) {
- return 0;
+ return;
}
if (ctx->sws_ctx && frame &&
@@ -633,35 +660,46 @@ static int add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *fra
frame->pts = ctx->cfra++;
}
- ret = avcodec_encode_video2(ctx->c, &packet, frame, &got_output);
+ int ret = avcodec_send_frame(ctx->c, frame);
if (ret < 0) {
- fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", ctx->cfra - 1, ctx->of->filename);
- return 0;
+ /* Can't send frame to encoder. This shouldn't happen. */
+ fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret));
+ return;
}
+ AVPacket *packet = av_packet_alloc();
+
+ while (ret >= 0) {
+ ret = avcodec_receive_packet(ctx->c, packet);
- if (got_output) {
- if (packet.pts != AV_NOPTS_VALUE) {
- packet.pts = av_rescale_q(packet.pts, ctx->c->time_base, ctx->st->time_base);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+ /* No more packets to flush. */
+ break;
}
- if (packet.dts != AV_NOPTS_VALUE) {
- packet.dts = av_rescale_q(packet.dts, ctx->c->time_base, ctx->st->time_base);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Error encoding proxy frame %d for '%s': %s\n",
+ ctx->cfra - 1,
+ ctx->of->url,
+ av_err2str(ret));
+ break;
}
- packet.stream_index = ctx->st->index;
+ packet->stream_index = ctx->st->index;
+ av_packet_rescale_ts(packet, ctx->c->time_base, ctx->st->time_base);
- if (av_interleaved_write_frame(ctx->of, &packet) != 0) {
+ int write_ret = av_interleaved_write_frame(ctx->of, packet);
+ if (write_ret != 0) {
fprintf(stderr,
"Error writing proxy frame %d "
- "into '%s'\n",
+ "into '%s': %s\n",
ctx->cfra - 1,
- ctx->of->filename);
- return 0;
+ ctx->of->url,
+ av_err2str(write_ret));
+ break;
}
-
- return 1;
}
- return 0;
+ av_packet_free(&packet);
}
static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback)
@@ -674,15 +712,15 @@ static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback)
}
if (!rollback) {
- while (add_to_proxy_output_ffmpeg(ctx, NULL)) {
- }
+ /* Flush the remaining packets. */
+ add_to_proxy_output_ffmpeg(ctx, NULL);
}
avcodec_flush_buffers(ctx->c);
av_write_trailer(ctx->of);
- avcodec_close(ctx->c);
+ avcodec_free_context(&ctx->c);
if (ctx->of->oformat) {
if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) {
@@ -777,7 +815,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
/* Find the video stream */
context->videoStream = -1;
for (i = 0; i < context->iFormatCtx->nb_streams; i++) {
- if (context->iFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ if (context->iFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
if (streamcount > 0) {
streamcount--;
continue;
@@ -794,9 +832,8 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
}
context->iStream = context->iFormatCtx->streams[context->videoStream];
- context->iCodecCtx = context->iStream->codec;
- context->iCodec = avcodec_find_decoder(context->iCodecCtx->codec_id);
+ context->iCodec = avcodec_find_decoder(context->iStream->codecpar->codec_id);
if (context->iCodec == NULL) {
avformat_close_input(&context->iFormatCtx);
@@ -804,7 +841,9 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
return NULL;
}
- context->iCodecCtx->workaround_bugs = 1;
+ context->iCodecCtx = avcodec_alloc_context3(NULL);
+ avcodec_parameters_to_context(context->iCodecCtx, context->iStream->codecpar);
+ context->iCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
if (context->iCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
context->iCodecCtx->thread_count = 0;
@@ -822,19 +861,19 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) {
avformat_close_input(&context->iFormatCtx);
+ avcodec_free_context(&context->iCodecCtx);
MEM_freeN(context);
return NULL;
}
for (i = 0; i < num_proxy_sizes; i++) {
if (proxy_sizes_in_use & proxy_sizes[i]) {
- context->proxy_ctx[i] = alloc_proxy_output_ffmpeg(
- anim,
- context->iStream,
- proxy_sizes[i],
- context->iCodecCtx->width * proxy_fac[i],
- av_get_cropped_height_from_codec(context->iCodecCtx) * proxy_fac[i],
- quality);
+ context->proxy_ctx[i] = alloc_proxy_output_ffmpeg(anim,
+ context->iStream,
+ proxy_sizes[i],
+ context->iCodecCtx->width * proxy_fac[i],
+ context->iCodecCtx->height * proxy_fac[i],
+ quality);
if (!context->proxy_ctx[i]) {
proxy_sizes_in_use &= ~proxy_sizes[i];
}
@@ -873,7 +912,7 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int
}
}
- avcodec_close(context->iCodecCtx);
+ avcodec_free_context(&context->iCodecCtx);
avformat_close_input(&context->iFormatCtx);
MEM_freeN(context);
@@ -938,23 +977,18 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
short *do_update,
float *progress)
{
- AVFrame *in_frame = 0;
- AVPacket next_packet;
+ AVFrame *in_frame = av_frame_alloc();
+ AVPacket *next_packet = av_packet_alloc();
uint64_t stream_size;
- memset(&next_packet, 0, sizeof(AVPacket));
-
- in_frame = av_frame_alloc();
-
stream_size = avio_size(context->iFormatCtx->pb);
context->frame_rate = av_q2d(av_guess_frame_rate(context->iFormatCtx, context->iStream, NULL));
context->pts_time_base = av_q2d(context->iStream->time_base);
- while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {
- int frame_finished = 0;
+ while (av_read_frame(context->iFormatCtx, next_packet) >= 0) {
float next_progress =
- (float)((int)floor(((double)next_packet.pos) * 100 / ((double)stream_size) + 0.5)) / 100;
+ (float)((int)floor(((double)next_packet->pos) * 100 / ((double)stream_size) + 0.5)) / 100;
if (*progress != next_progress) {
*progress = next_progress;
@@ -962,50 +996,59 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
}
if (*stop) {
- av_free_packet(&next_packet);
break;
}
- if (next_packet.stream_index == context->videoStream) {
- if (next_packet.flags & AV_PKT_FLAG_KEY) {
+ if (next_packet->stream_index == context->videoStream) {
+ if (next_packet->flags & AV_PKT_FLAG_KEY) {
context->last_seek_pos = context->seek_pos;
context->last_seek_pos_dts = context->seek_pos_dts;
- context->seek_pos = next_packet.pos;
- context->seek_pos_dts = next_packet.dts;
- context->seek_pos_pts = next_packet.pts;
+ context->seek_pos = next_packet->pos;
+ context->seek_pos_dts = next_packet->dts;
+ context->seek_pos_pts = next_packet->pts;
}
- avcodec_decode_video2(context->iCodecCtx, in_frame, &frame_finished, &next_packet);
- }
+ int ret = avcodec_send_packet(context->iCodecCtx, next_packet);
+ while (ret >= 0) {
+ ret = avcodec_receive_frame(context->iCodecCtx, in_frame);
- if (frame_finished) {
- index_rebuild_ffmpeg_proc_decoded_frame(context, &next_packet, in_frame);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+ /* No more frames to flush. */
+ break;
+ }
+ if (ret < 0) {
+ fprintf(stderr, "Error decoding proxy frame: %s\n", av_err2str(ret));
+ break;
+ }
+ index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame);
+ }
}
- av_free_packet(&next_packet);
}
/* process pictures still stuck in decoder engine after EOF
- * according to ffmpeg docs using 0-size packets.
+ * according to ffmpeg docs using NULL packets.
*
* At least, if we haven't already stopped... */
- /* this creates the 0-size packet and prevents a memory leak. */
- av_free_packet(&next_packet);
-
if (!*stop) {
- int frame_finished;
-
- do {
- frame_finished = 0;
+ int ret = avcodec_send_packet(context->iCodecCtx, NULL);
- avcodec_decode_video2(context->iCodecCtx, in_frame, &frame_finished, &next_packet);
+ while (ret >= 0) {
+ ret = avcodec_receive_frame(context->iCodecCtx, in_frame);
- if (frame_finished) {
- index_rebuild_ffmpeg_proc_decoded_frame(context, &next_packet, in_frame);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+ /* No more frames to flush. */
+ break;
}
- } while (frame_finished);
+ if (ret < 0) {
+ fprintf(stderr, "Error flushing proxy frame: %s\n", av_err2str(ret));
+ break;
+ }
+ index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame);
+ }
}
+ av_packet_free(&next_packet);
av_free(in_frame);
return 1;
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 64dad5de902..fabf6c5c3bd 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -245,7 +245,6 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis
void IMB_ffmpeg_init(void)
{
- av_register_all();
avdevice_register_all();
ffmpeg_last_error[0] = '\0';
@@ -269,7 +268,6 @@ static int isffmpeg(const char *filepath)
unsigned int i;
int videoStream;
AVCodec *pCodec;
- AVCodecContext *pCodecCtx;
if (BLI_path_extension_check_n(filepath,
".swf",
@@ -310,8 +308,8 @@ static int isffmpeg(const char *filepath)
/* Find the first video stream */
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
- if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codec &&
- (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) {
+ if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codecpar &&
+ (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) {
videoStream = i;
break;
}
@@ -322,21 +320,15 @@ static int isffmpeg(const char *filepath)
return 0;
}
- pCodecCtx = pFormatCtx->streams[videoStream]->codec;
+ AVCodecParameters *codec_par = pFormatCtx->streams[videoStream]->codecpar;
/* Find the decoder for the video stream */
- pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
+ pCodec = avcodec_find_decoder(codec_par->codec_id);
if (pCodec == NULL) {
avformat_close_input(&pFormatCtx);
return 0;
}
- if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
- avformat_close_input(&pFormatCtx);
- return 0;
- }
-
- avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 1;