674 lines
21 KiB
Diff
674 lines
21 KiB
Diff
diff -ur blender-2.76/CMakeLists.txt blender-2.76.ffmpeg/CMakeLists.txt
|
|
--- blender-2.76/CMakeLists.txt 2015-10-12 00:58:22.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/CMakeLists.txt 2016-04-16 15:31:11.524037254 +0200
|
|
@@ -982,7 +982,7 @@
|
|
|
|
if(WITH_CODEC_FFMPEG)
|
|
set(FFMPEG /usr CACHE PATH "FFMPEG Directory")
|
|
- set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries")
|
|
+ set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale avfilter CACHE STRING "FFMPEG Libraries")
|
|
|
|
mark_as_advanced(FFMPEG)
|
|
|
|
diff -ur blender-2.76/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp blender-2.76.ffmpeg/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
|
|
--- blender-2.76/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp 2015-10-07 02:09:33.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp 2016-04-16 15:31:11.524037254 +0200
|
|
@@ -58,9 +58,9 @@
|
|
got_frame = 0;
|
|
|
|
if(!frame)
|
|
- frame = avcodec_alloc_frame();
|
|
+ frame = av_frame_alloc();
|
|
else
|
|
- avcodec_get_frame_defaults(frame);
|
|
+ av_frame_unref(frame);
|
|
|
|
read_length = avcodec_decode_audio4(m_codecCtx, frame, &got_frame, &packet);
|
|
if(read_length < 0)
|
|
diff -ur blender-2.76/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp blender-2.76.ffmpeg/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
|
|
--- blender-2.76/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp 2015-10-07 02:09:33.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp 2016-04-16 15:31:11.524037254 +0200
|
|
@@ -202,7 +202,7 @@
|
|
m_frame = av_frame_alloc();
|
|
if (!m_frame)
|
|
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
|
|
- avcodec_get_frame_defaults(m_frame);
|
|
+ av_frame_unref(m_frame);
|
|
m_frame->linesize[0] = m_input_size * samplesize;
|
|
m_frame->format = m_codecCtx->sample_fmt;
|
|
m_frame->nb_samples = m_input_size;
|
|
diff -ur blender-2.76/source/blender/blenkernel/intern/writeffmpeg.c blender-2.76.ffmpeg/source/blender/blenkernel/intern/writeffmpeg.c
|
|
--- blender-2.76/source/blender/blenkernel/intern/writeffmpeg.c 2015-10-12 00:58:22.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/blender/blenkernel/intern/writeffmpeg.c 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -138,8 +138,8 @@
|
|
context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate;
|
|
|
|
#ifdef FFMPEG_HAVE_ENCODE_AUDIO2
|
|
- frame = avcodec_alloc_frame();
|
|
- avcodec_get_frame_defaults(frame);
|
|
+ frame = av_frame_alloc();
|
|
+ av_frame_unref(frame);
|
|
frame->pts = context->audio_time / av_q2d(c->time_base);
|
|
frame->nb_samples = context->audio_input_samples;
|
|
frame->format = c->sample_fmt;
|
|
@@ -172,7 +172,7 @@
|
|
}
|
|
|
|
if (!got_output) {
|
|
- avcodec_free_frame(&frame);
|
|
+ av_frame_free(&frame);
|
|
return 0;
|
|
}
|
|
#else
|
|
@@ -202,7 +202,7 @@
|
|
if (av_interleaved_write_frame(context->outfile, &pkt) != 0) {
|
|
fprintf(stderr, "Error writing audio packet!\n");
|
|
if (frame)
|
|
- avcodec_free_frame(&frame);
|
|
+ av_frame_free(&frame);
|
|
return -1;
|
|
}
|
|
|
|
@@ -210,7 +210,7 @@
|
|
}
|
|
|
|
if (frame)
|
|
- avcodec_free_frame(&frame);
|
|
+ av_frame_free(&frame);
|
|
|
|
return 0;
|
|
}
|
|
@@ -224,7 +224,7 @@
|
|
int size;
|
|
|
|
/* allocate space for the struct */
|
|
- f = avcodec_alloc_frame();
|
|
+ f = av_frame_alloc();
|
|
if (!f) return NULL;
|
|
size = avpicture_get_size(pix_fmt, width, height);
|
|
/* allocate the actual picture buffer */
|
|
@@ -363,8 +363,8 @@
|
|
int height = c->height;
|
|
AVFrame *rgb_frame;
|
|
|
|
- if (c->pix_fmt != PIX_FMT_BGR32) {
|
|
- rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height);
|
|
+ if (c->pix_fmt != AV_PIX_FMT_BGR32) {
|
|
+ rgb_frame = alloc_picture(AV_PIX_FMT_BGR32, width, height);
|
|
if (!rgb_frame) {
|
|
BKE_report(reports, RPT_ERROR, "Could not allocate temporary frame");
|
|
return NULL;
|
|
@@ -414,14 +414,14 @@
|
|
}
|
|
}
|
|
|
|
- if (c->pix_fmt != PIX_FMT_BGR32) {
|
|
+ if (c->pix_fmt != AV_PIX_FMT_BGR32) {
|
|
sws_scale(context->img_convert_ctx, (const uint8_t *const *) rgb_frame->data,
|
|
rgb_frame->linesize, 0, c->height,
|
|
context->current_frame->data, context->current_frame->linesize);
|
|
delete_picture(rgb_frame);
|
|
}
|
|
|
|
- context->current_frame->format = PIX_FMT_BGR32;
|
|
+ context->current_frame->format = AV_PIX_FMT_BGR32;
|
|
context->current_frame->width = width;
|
|
context->current_frame->height = height;
|
|
|
|
@@ -586,12 +586,12 @@
|
|
}
|
|
else {
|
|
/* makes HuffYUV happy ... */
|
|
- c->pix_fmt = PIX_FMT_YUV422P;
|
|
+ c->pix_fmt = AV_PIX_FMT_YUV422P;
|
|
}
|
|
|
|
if (context->ffmpeg_type == FFMPEG_XVID) {
|
|
/* arghhhh ... */
|
|
- c->pix_fmt = PIX_FMT_YUV420P;
|
|
+ c->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
|
|
}
|
|
|
|
@@ -604,26 +604,26 @@
|
|
/* Keep lossless encodes in the RGB domain. */
|
|
if (codec_id == AV_CODEC_ID_HUFFYUV) {
|
|
if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
|
|
- c->pix_fmt = PIX_FMT_BGRA;
|
|
+ c->pix_fmt = AV_PIX_FMT_BGRA;
|
|
}
|
|
else {
|
|
- c->pix_fmt = PIX_FMT_RGB32;
|
|
+ c->pix_fmt = AV_PIX_FMT_RGB32;
|
|
}
|
|
}
|
|
|
|
if (codec_id == AV_CODEC_ID_FFV1) {
|
|
- c->pix_fmt = PIX_FMT_RGB32;
|
|
+ c->pix_fmt = AV_PIX_FMT_RGB32;
|
|
}
|
|
|
|
if (codec_id == AV_CODEC_ID_QTRLE) {
|
|
if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
|
|
- c->pix_fmt = PIX_FMT_ARGB;
|
|
+ c->pix_fmt = AV_PIX_FMT_ARGB;
|
|
}
|
|
}
|
|
|
|
if (codec_id == AV_CODEC_ID_PNG) {
|
|
if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
|
|
- c->pix_fmt = PIX_FMT_RGBA;
|
|
+ c->pix_fmt = AV_PIX_FMT_RGBA;
|
|
}
|
|
}
|
|
|
|
@@ -661,7 +661,7 @@
|
|
|
|
context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
|
|
|
|
- context->img_convert_ctx = sws_getContext(c->width, c->height, PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
|
|
+ context->img_convert_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC,
|
|
NULL, NULL, NULL);
|
|
return st;
|
|
}
|
|
diff -ur blender-2.76/source/blender/imbuf/intern/anim_movie.c blender-2.76.ffmpeg/source/blender/imbuf/intern/anim_movie.c
|
|
--- blender-2.76/source/blender/imbuf/intern/anim_movie.c 2015-10-07 02:09:33.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/blender/imbuf/intern/anim_movie.c 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -474,6 +474,10 @@
|
|
const int *inv_table;
|
|
#endif
|
|
|
|
+ anim->last_width = -1;
|
|
+ anim->last_height = -1;
|
|
+ anim->last_pixfmt = AV_PIX_FMT_NONE;
|
|
+
|
|
if (anim == NULL) return(-1);
|
|
|
|
streamcount = anim->streamindex;
|
|
@@ -562,21 +566,21 @@
|
|
anim->next_pts = -1;
|
|
anim->next_packet.stream_index = -1;
|
|
|
|
- anim->pFrame = avcodec_alloc_frame();
|
|
+ anim->pFrame = av_frame_alloc();
|
|
anim->pFrameComplete = false;
|
|
- anim->pFrameDeinterlaced = avcodec_alloc_frame();
|
|
- anim->pFrameRGB = avcodec_alloc_frame();
|
|
+ anim->pFrameDeinterlaced = av_frame_alloc();
|
|
+ anim->pFrameRGB = av_frame_alloc();
|
|
|
|
- if (avpicture_get_size(PIX_FMT_RGBA, anim->x, anim->y) !=
|
|
+ if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) !=
|
|
anim->x * anim->y * 4)
|
|
{
|
|
fprintf(stderr,
|
|
"ffmpeg has changed alloc scheme ... ARGHHH!\n");
|
|
avcodec_close(anim->pCodecCtx);
|
|
avformat_close_input(&anim->pFormatCtx);
|
|
- av_free(anim->pFrameRGB);
|
|
- av_free(anim->pFrameDeinterlaced);
|
|
- av_free(anim->pFrame);
|
|
+ av_frame_free(&anim->pFrameRGB);
|
|
+ av_frame_free(&anim->pFrameDeinterlaced);
|
|
+ av_frame_free(&anim->pFrame);
|
|
anim->pCodecCtx = NULL;
|
|
return -1;
|
|
}
|
|
@@ -606,7 +610,7 @@
|
|
anim->pCodecCtx->pix_fmt,
|
|
anim->x,
|
|
anim->y,
|
|
- PIX_FMT_RGBA,
|
|
+ AV_PIX_FMT_RGBA,
|
|
SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT,
|
|
NULL, NULL, NULL);
|
|
|
|
@@ -615,9 +619,9 @@
|
|
"Can't transform color space??? Bailing out...\n");
|
|
avcodec_close(anim->pCodecCtx);
|
|
avformat_close_input(&anim->pFormatCtx);
|
|
- av_free(anim->pFrameRGB);
|
|
- av_free(anim->pFrameDeinterlaced);
|
|
- av_free(anim->pFrame);
|
|
+ av_frame_free(&anim->pFrameRGB);
|
|
+ av_frame_free(&anim->pFrameDeinterlaced);
|
|
+ av_frame_free(&anim->pFrame);
|
|
anim->pCodecCtx = NULL;
|
|
return -1;
|
|
}
|
|
@@ -644,6 +648,74 @@
|
|
return (0);
|
|
}
|
|
|
|
+static void delete_filter_graph(struct anim *anim) {
|
|
+ if (anim->filter_graph) {
|
|
+ av_frame_free(&anim->filter_frame);
|
|
+ avfilter_graph_free(&anim->filter_graph);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int init_filter_graph(struct anim *anim, enum AVPixelFormat pixfmt, int width, int height) {
|
|
+ AVFilterInOut *inputs = NULL, *outputs = NULL;
|
|
+ char args[512];
|
|
+ int res;
|
|
+
|
|
+ delete_filter_graph(anim);
|
|
+ anim->filter_graph = avfilter_graph_alloc();
|
|
+ snprintf(args, sizeof(args),
|
|
+ "buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/1:pixel_aspect=0/1[in];"
|
|
+ "[in]yadif[out];"
|
|
+ "[out]buffersink",
|
|
+ width, height, pixfmt);
|
|
+ res = avfilter_graph_parse2(anim->filter_graph, args, &inputs, &outputs);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ if(inputs || outputs)
|
|
+ return -1;
|
|
+ res = avfilter_graph_config(anim->filter_graph, NULL);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+
|
|
+ anim->buffersrc_ctx = avfilter_graph_get_filter(anim->filter_graph, "Parsed_buffer_0");
|
|
+ anim->buffersink_ctx = avfilter_graph_get_filter(anim->filter_graph, "Parsed_buffersink_2");
|
|
+ if (!anim->buffersrc_ctx || !anim->buffersink_ctx)
|
|
+ return -1;
|
|
+ anim->filter_frame = av_frame_alloc();
|
|
+ anim->last_width = width;
|
|
+ anim->last_height = height;
|
|
+ anim->last_pixfmt = pixfmt;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int process_filter_graph(struct anim *anim, AVPicture *dst, const AVPicture *src,
|
|
+ enum AVPixelFormat pixfmt, int width, int height) {
|
|
+ int res;
|
|
+
|
|
+ if (!anim->filter_graph || width != anim->last_width ||
|
|
+ height != anim->last_height || pixfmt != anim->last_pixfmt) {
|
|
+ res = init_filter_graph(anim, pixfmt, width, height);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ }
|
|
+
|
|
+ memcpy(anim->filter_frame->data, src->data, sizeof(src->data));
|
|
+ memcpy(anim->filter_frame->linesize, src->linesize, sizeof(src->linesize));
|
|
+ anim->filter_frame->width = width;
|
|
+ anim->filter_frame->height = height;
|
|
+ anim->filter_frame->format = pixfmt;
|
|
+ res = av_buffersrc_add_frame(anim->buffersrc_ctx, anim->filter_frame);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ res = av_buffersink_get_frame(anim->buffersink_ctx, anim->filter_frame);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ av_picture_copy(dst, (const AVPicture *) anim->filter_frame, pixfmt, width, height);
|
|
+ av_frame_unref(anim->filter_frame);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* postprocess the image in anim->pFrame and do color conversion
|
|
* and deinterlacing stuff.
|
|
*
|
|
@@ -677,7 +749,8 @@
|
|
|
|
|
|
if (anim->ib_flags & IB_animdeinterlace) {
|
|
- if (avpicture_deinterlace(
|
|
+ if (process_filter_graph(
|
|
+ anim,
|
|
(AVPicture *)
|
|
anim->pFrameDeinterlaced,
|
|
(const AVPicture *)
|
|
@@ -695,7 +768,7 @@
|
|
|
|
avpicture_fill((AVPicture *) anim->pFrameRGB,
|
|
(unsigned char *) ibuf->rect,
|
|
- PIX_FMT_RGBA, anim->x, anim->y);
|
|
+ AV_PIX_FMT_RGBA, anim->x, anim->y);
|
|
|
|
if (ENDIAN_ORDER == B_ENDIAN) {
|
|
int *dstStride = anim->pFrameRGB->linesize;
|
|
@@ -1138,16 +1211,18 @@
|
|
{
|
|
if (anim == NULL) return;
|
|
|
|
+ delete_filter_graph(anim);
|
|
+
|
|
if (anim->pCodecCtx) {
|
|
avcodec_close(anim->pCodecCtx);
|
|
avformat_close_input(&anim->pFormatCtx);
|
|
- av_free(anim->pFrameRGB);
|
|
- av_free(anim->pFrame);
|
|
+ av_frame_free(&anim->pFrameRGB);
|
|
+ av_frame_free(&anim->pFrame);
|
|
|
|
if (anim->ib_flags & IB_animdeinterlace) {
|
|
MEM_freeN(anim->pFrameDeinterlaced->data[0]);
|
|
}
|
|
- av_free(anim->pFrameDeinterlaced);
|
|
+ av_frame_free(&anim->pFrameDeinterlaced);
|
|
sws_freeContext(anim->img_convert_ctx);
|
|
IMB_freeImBuf(anim->last_frame);
|
|
if (anim->next_packet.stream_index != -1) {
|
|
diff -ur blender-2.76/source/blender/imbuf/intern/IMB_anim.h blender-2.76.ffmpeg/source/blender/imbuf/intern/IMB_anim.h
|
|
--- blender-2.76/source/blender/imbuf/intern/IMB_anim.h 2015-10-07 02:09:33.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/blender/imbuf/intern/IMB_anim.h 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -76,6 +76,9 @@
|
|
# include <libavformat/avformat.h>
|
|
# include <libavcodec/avcodec.h>
|
|
# include <libswscale/swscale.h>
|
|
+# include <libavfilter/avfilter.h>
|
|
+# include <libavfilter/buffersrc.h>
|
|
+# include <libavfilter/buffersink.h>
|
|
#endif
|
|
|
|
#ifdef WITH_REDCODE
|
|
@@ -175,6 +178,14 @@
|
|
int64_t last_pts;
|
|
int64_t next_pts;
|
|
AVPacket next_packet;
|
|
+
|
|
+ AVFilterContext *buffersink_ctx;
|
|
+ AVFilterContext *buffersrc_ctx;
|
|
+ AVFilterGraph *filter_graph;
|
|
+ AVFrame *filter_frame;
|
|
+ int last_width;
|
|
+ int last_height;
|
|
+ enum AVPixelFormat last_pixfmt;
|
|
#endif
|
|
|
|
#ifdef WITH_REDCODE
|
|
diff -ur blender-2.76/source/blender/imbuf/intern/indexer.c blender-2.76.ffmpeg/source/blender/imbuf/intern/indexer.c
|
|
--- blender-2.76/source/blender/imbuf/intern/indexer.c 2015-10-07 02:09:33.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/blender/imbuf/intern/indexer.c 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -519,7 +519,7 @@
|
|
rv->c->pix_fmt = rv->codec->pix_fmts[0];
|
|
}
|
|
else {
|
|
- rv->c->pix_fmt = PIX_FMT_YUVJ420P;
|
|
+ rv->c->pix_fmt = AV_PIX_FMT_YUVJ420P;
|
|
}
|
|
|
|
rv->c->sample_aspect_ratio =
|
|
@@ -554,7 +554,7 @@
|
|
if (st->codec->width != width || st->codec->height != height ||
|
|
st->codec->pix_fmt != rv->c->pix_fmt)
|
|
{
|
|
- rv->frame = avcodec_alloc_frame();
|
|
+ rv->frame = av_frame_alloc();
|
|
avpicture_fill((AVPicture *) rv->frame,
|
|
MEM_mallocN(avpicture_get_size(
|
|
rv->c->pix_fmt,
|
|
@@ -675,7 +675,7 @@
|
|
sws_freeContext(ctx->sws_ctx);
|
|
|
|
MEM_freeN(ctx->frame->data[0]);
|
|
- av_free(ctx->frame);
|
|
+ av_frame_free(&ctx->frame);
|
|
}
|
|
|
|
get_proxy_filename(ctx->anim, ctx->proxy_size,
|
|
@@ -905,7 +905,7 @@
|
|
|
|
memset(&next_packet, 0, sizeof(AVPacket));
|
|
|
|
- in_frame = avcodec_alloc_frame();
|
|
+ in_frame = av_frame_alloc();
|
|
|
|
stream_size = avio_size(context->iFormatCtx->pb);
|
|
|
|
@@ -973,7 +973,7 @@
|
|
} while (frame_finished);
|
|
}
|
|
|
|
- av_free(in_frame);
|
|
+ av_frame_free(&in_frame);
|
|
|
|
return 1;
|
|
}
|
|
diff -ur blender-2.76/source/gameengine/VideoTexture/VideoFFmpeg.cpp blender-2.76.ffmpeg/source/gameengine/VideoTexture/VideoFFmpeg.cpp
|
|
--- blender-2.76/source/gameengine/VideoTexture/VideoFFmpeg.cpp 2015-10-12 00:58:22.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/gameengine/VideoTexture/VideoFFmpeg.cpp 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -79,11 +79,16 @@
|
|
BLI_listbase_clear(&m_frameCacheBase);
|
|
BLI_listbase_clear(&m_packetCacheFree);
|
|
BLI_listbase_clear(&m_packetCacheBase);
|
|
+ last_width = -1;
|
|
+ last_height = -1;
|
|
+ last_pixfmt = AV_PIX_FMT_NONE;
|
|
+
|
|
}
|
|
|
|
// destructor
|
|
VideoFFmpeg::~VideoFFmpeg ()
|
|
{
|
|
+ delete_filter_graph(this);
|
|
}
|
|
|
|
void VideoFFmpeg::refresh(void)
|
|
@@ -140,23 +145,23 @@
|
|
AVFrame *VideoFFmpeg::allocFrameRGB()
|
|
{
|
|
AVFrame *frame;
|
|
- frame = avcodec_alloc_frame();
|
|
+ frame = av_frame_alloc();
|
|
if (m_format == RGBA32)
|
|
{
|
|
avpicture_fill((AVPicture*)frame,
|
|
(uint8_t*)MEM_callocN(avpicture_get_size(
|
|
- PIX_FMT_RGBA,
|
|
+ AV_PIX_FMT_RGBA,
|
|
m_codecCtx->width, m_codecCtx->height),
|
|
"ffmpeg rgba"),
|
|
- PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height);
|
|
+ AV_PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height);
|
|
} else
|
|
{
|
|
avpicture_fill((AVPicture*)frame,
|
|
(uint8_t*)MEM_callocN(avpicture_get_size(
|
|
- PIX_FMT_RGB24,
|
|
+ AV_PIX_FMT_RGB24,
|
|
m_codecCtx->width, m_codecCtx->height),
|
|
"ffmpeg rgb"),
|
|
- PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height);
|
|
+ AV_PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height);
|
|
}
|
|
return frame;
|
|
}
|
|
@@ -236,8 +241,8 @@
|
|
m_codecCtx = codecCtx;
|
|
m_formatCtx = formatCtx;
|
|
m_videoStream = videoStream;
|
|
- m_frame = avcodec_alloc_frame();
|
|
- m_frameDeinterlaced = avcodec_alloc_frame();
|
|
+ m_frame = av_frame_alloc();
|
|
+ m_frameDeinterlaced = av_frame_alloc();
|
|
|
|
// allocate buffer if deinterlacing is required
|
|
avpicture_fill((AVPicture*)m_frameDeinterlaced,
|
|
@@ -248,10 +253,10 @@
|
|
m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
|
|
|
|
// check if the pixel format supports Alpha
|
|
- if (m_codecCtx->pix_fmt == PIX_FMT_RGB32 ||
|
|
- m_codecCtx->pix_fmt == PIX_FMT_BGR32 ||
|
|
- m_codecCtx->pix_fmt == PIX_FMT_RGB32_1 ||
|
|
- m_codecCtx->pix_fmt == PIX_FMT_BGR32_1)
|
|
+ if (m_codecCtx->pix_fmt == AV_PIX_FMT_RGB32 ||
|
|
+ m_codecCtx->pix_fmt == AV_PIX_FMT_BGR32 ||
|
|
+ m_codecCtx->pix_fmt == AV_PIX_FMT_RGB32_1 ||
|
|
+ m_codecCtx->pix_fmt == AV_PIX_FMT_BGR32_1)
|
|
{
|
|
// allocate buffer to store final decoded frame
|
|
m_format = RGBA32;
|
|
@@ -262,7 +267,7 @@
|
|
m_codecCtx->pix_fmt,
|
|
m_codecCtx->width,
|
|
m_codecCtx->height,
|
|
- PIX_FMT_RGBA,
|
|
+ AV_PIX_FMT_RGBA,
|
|
SWS_FAST_BILINEAR,
|
|
NULL, NULL, NULL);
|
|
} else
|
|
@@ -276,7 +281,7 @@
|
|
m_codecCtx->pix_fmt,
|
|
m_codecCtx->width,
|
|
m_codecCtx->height,
|
|
- PIX_FMT_RGB24,
|
|
+ AV_PIX_FMT_RGB24,
|
|
SWS_FAST_BILINEAR,
|
|
NULL, NULL, NULL);
|
|
}
|
|
@@ -293,13 +298,81 @@
|
|
av_free(m_frameDeinterlaced);
|
|
m_frameDeinterlaced = NULL;
|
|
MEM_freeN(m_frameRGB->data[0]);
|
|
- av_free(m_frameRGB);
|
|
+ av_frame_free(&m_frameRGB);
|
|
m_frameRGB = NULL;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
+void VideoFFmpeg::delete_filter_graph(VideoFFmpeg* video) {
|
|
+ if (video->filter_graph) {
|
|
+ av_frame_free(&video->filter_frame);
|
|
+ avfilter_graph_free(&video->filter_graph);
|
|
+ }
|
|
+}
|
|
+
|
|
+int VideoFFmpeg::init_filter_graph(VideoFFmpeg* video, enum AVPixelFormat pixfmt, int width, int height) {
|
|
+ AVFilterInOut *inputs = NULL, *outputs = NULL;
|
|
+ char args[512];
|
|
+ int res;
|
|
+
|
|
+ delete_filter_graph(video);
|
|
+ video->filter_graph = avfilter_graph_alloc();
|
|
+ snprintf(args, sizeof(args),
|
|
+ "buffer=video_size=%dx%d:pix_fmt=%d:time_base=1/1:pixel_aspect=0/1[in];"
|
|
+ "[in]yadif[out];"
|
|
+ "[out]buffersink",
|
|
+ width, height, pixfmt);
|
|
+ res = avfilter_graph_parse2(video->filter_graph, args, &inputs, &outputs);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ if(inputs || outputs)
|
|
+ return -1;
|
|
+ res = avfilter_graph_config(video->filter_graph, NULL);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+
|
|
+ video->buffersrc_ctx = avfilter_graph_get_filter(video->filter_graph, "Parsed_buffer_0");
|
|
+ video->buffersink_ctx = avfilter_graph_get_filter(video->filter_graph, "Parsed_buffersink_2");
|
|
+ if (!video->buffersrc_ctx || !video->buffersink_ctx)
|
|
+ return -1;
|
|
+ video->filter_frame = av_frame_alloc();
|
|
+ video->last_width = width;
|
|
+ video->last_height = height;
|
|
+ video->last_pixfmt = pixfmt;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int VideoFFmpeg::process_filter_graph(VideoFFmpeg* video, AVPicture *dst, const AVPicture *src,
|
|
+ enum AVPixelFormat pixfmt, int width, int height) {
|
|
+ int res;
|
|
+
|
|
+ if (!video->filter_graph || width != video->last_width ||
|
|
+ height != video->last_height || pixfmt != video->last_pixfmt) {
|
|
+ res = init_filter_graph(video, pixfmt, width, height);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ }
|
|
+
|
|
+ memcpy(video->filter_frame->data, src->data, sizeof(src->data));
|
|
+ memcpy(video->filter_frame->linesize, src->linesize, sizeof(src->linesize));
|
|
+ video->filter_frame->width = width;
|
|
+ video->filter_frame->height = height;
|
|
+ video->filter_frame->format = pixfmt;
|
|
+ res = av_buffersrc_add_frame(video->buffersrc_ctx, video->filter_frame);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ res = av_buffersink_get_frame(video->buffersink_ctx, video->filter_frame);
|
|
+ if (res < 0)
|
|
+ return res;
|
|
+ av_picture_copy(dst, (const AVPicture *) video->filter_frame, pixfmt, width, height);
|
|
+ av_frame_unref(video->filter_frame);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
* This thread is used to load video frame asynchronously.
|
|
* It provides a frame caching service.
|
|
@@ -392,7 +465,7 @@
|
|
{
|
|
if (video->m_deinterlace)
|
|
{
|
|
- if (avpicture_deinterlace(
|
|
+ if (process_filter_graph(video,
|
|
(AVPicture*) video->m_frameDeinterlaced,
|
|
(const AVPicture*) video->m_frame,
|
|
video->m_codecCtx->pix_fmt,
|
|
@@ -486,14 +559,14 @@
|
|
{
|
|
BLI_remlink(&m_frameCacheBase, frame);
|
|
MEM_freeN(frame->frame->data[0]);
|
|
- av_free(frame->frame);
|
|
+ av_frame_free(&frame->frame);
|
|
delete frame;
|
|
}
|
|
while ((frame = (CacheFrame *)m_frameCacheFree.first) != NULL)
|
|
{
|
|
BLI_remlink(&m_frameCacheFree, frame);
|
|
MEM_freeN(frame->frame->data[0]);
|
|
- av_free(frame->frame);
|
|
+ av_frame_free(&frame->frame);
|
|
delete frame;
|
|
}
|
|
while ((packet = (CachePacket *)m_packetCacheBase.first) != NULL)
|
|
@@ -1057,7 +1130,7 @@
|
|
|
|
if (m_deinterlace)
|
|
{
|
|
- if (avpicture_deinterlace(
|
|
+ if (process_filter_graph(this,
|
|
(AVPicture*) m_frameDeinterlaced,
|
|
(const AVPicture*) m_frame,
|
|
m_codecCtx->pix_fmt,
|
|
diff -ur blender-2.76/source/gameengine/VideoTexture/VideoFFmpeg.h blender-2.76.ffmpeg/source/gameengine/VideoTexture/VideoFFmpeg.h
|
|
--- blender-2.76/source/gameengine/VideoTexture/VideoFFmpeg.h 2015-10-10 10:20:56.000000000 +0200
|
|
+++ blender-2.76.ffmpeg/source/gameengine/VideoTexture/VideoFFmpeg.h 2016-04-16 15:31:11.527370628 +0200
|
|
@@ -39,6 +39,9 @@
|
|
extern "C" {
|
|
#include <pthread.h>
|
|
#include "ffmpeg_compat.h"
|
|
+#include <libavfilter/avfilter.h>
|
|
+#include <libavfilter/buffersrc.h>
|
|
+#include <libavfilter/buffersink.h>
|
|
#include "DNA_listBase.h"
|
|
#include "BLI_threads.h"
|
|
#include "BLI_blenlib.h"
|
|
@@ -207,6 +210,18 @@
|
|
|
|
AVFrame *allocFrameRGB();
|
|
static void *cacheThread(void *);
|
|
+
|
|
+ AVFilterContext *buffersink_ctx;
|
|
+ AVFilterContext *buffersrc_ctx;
|
|
+ AVFilterGraph *filter_graph;
|
|
+ AVFrame *filter_frame;
|
|
+ int last_width;
|
|
+ int last_height;
|
|
+ enum AVPixelFormat last_pixfmt;
|
|
+
|
|
+ static void delete_filter_graph(VideoFFmpeg* video);
|
|
+ static int init_filter_graph(VideoFFmpeg* video, enum AVPixelFormat pixfmt, int width, int height);
|
|
+ static int process_filter_graph(VideoFFmpeg* video, AVPicture *dst, const AVPicture *src, enum AVPixelFormat pixfmt, int width, int height);
|
|
};
|
|
|
|
inline VideoFFmpeg *getFFmpeg(PyImage *self)
|