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/intern/anim.c')
-rw-r--r--source/blender/imbuf/intern/anim.c292
1 files changed, 162 insertions, 130 deletions
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c
index bfc3433875d..096ed499f85 100644
--- a/source/blender/imbuf/intern/anim.c
+++ b/source/blender/imbuf/intern/anim.c
@@ -60,6 +60,8 @@
#include "BLI_blenlib.h" /* BLI_remlink BLI_filesize BLI_addtail
BLI_countlist BLI_stringdec */
+#include "MEM_guardedalloc.h"
+
#include "DNA_userdef_types.h"
#include "BKE_global.h"
#include "BKE_depsgraph.h"
@@ -685,6 +687,116 @@ static int startffmpeg(struct anim * anim) {
return (0);
}
+static void ffmpeg_postprocess(struct anim * anim, ImBuf * ibuf,
+ int * filter_y)
+{
+ AVFrame * input = anim->pFrame;
+
+ /* This means the data wasnt read properly,
+ this check stops crashing */
+ if (input->data[0]==0 && input->data[1]==0
+ && input->data[2]==0 && input->data[3]==0){
+ fprintf(stderr, "ffmpeg_fetchibuf: "
+ "data not read properly...\n");
+ return;
+ }
+
+ 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) {
+ *filter_y = 1;
+ } else {
+ input = anim->pFrameDeinterlaced;
+ }
+ }
+
+ if (ENDIAN_ORDER == B_ENDIAN) {
+ int * dstStride = anim->pFrameRGB->linesize;
+ uint8_t** dst = anim->pFrameRGB->data;
+ int dstStride2[4] = { dstStride[0], 0, 0, 0 };
+ uint8_t* dst2[4] = { dst[0], 0, 0, 0 };
+ int x,y,h,w;
+ unsigned char* bottom;
+ unsigned char* top;
+
+ sws_scale(anim->img_convert_ctx,
+ (const uint8_t * const *)input->data,
+ input->linesize,
+ 0,
+ anim->pCodecCtx->height,
+ dst2,
+ dstStride2);
+
+ /* workaround: sws_scale bug
+ sets alpha = 0 and compensate
+ for altivec-bugs and flipy... */
+
+ bottom = (unsigned char*) ibuf->rect;
+ top = bottom + ibuf->x * (ibuf->y-1) * 4;
+
+ h = (ibuf->y + 1) / 2;
+ w = ibuf->x;
+
+ for (y = 0; y < h; y++) {
+ unsigned char tmp[4];
+ unsigned int * tmp_l =
+ (unsigned int*) tmp;
+ tmp[3] = 0xff;
+
+ for (x = 0; x < w; x++) {
+ tmp[0] = bottom[0];
+ tmp[1] = bottom[1];
+ tmp[2] = bottom[2];
+
+ bottom[0] = top[0];
+ bottom[1] = top[1];
+ bottom[2] = top[2];
+ bottom[3] = 0xff;
+
+ *(unsigned int*) top = *tmp_l;
+
+ bottom +=4;
+ top += 4;
+ }
+ top -= 8 * w;
+ }
+ } else {
+ int * dstStride = anim->pFrameRGB->linesize;
+ uint8_t** dst = anim->pFrameRGB->data;
+ int dstStride2[4] = { -dstStride[0], 0, 0, 0 };
+ uint8_t* dst2[4] = { dst[0] + (anim->y - 1)*dstStride[0],
+ 0, 0, 0 };
+ int i;
+ unsigned char* r;
+
+ sws_scale(anim->img_convert_ctx,
+ (const uint8_t * const *)input->data,
+ input->linesize,
+ 0,
+ anim->pCodecCtx->height,
+ dst2,
+ dstStride2);
+
+ r = (unsigned char*) ibuf->rect;
+
+ /* workaround sws_scale bug: older version of
+ sws_scale set alpha = 0... */
+ if (r[3] == 0) {
+ for (i = 0; i < ibuf->x * ibuf->y; i++) {
+ r[3] = 0xff;
+ r += 4;
+ }
+ }
+ }
+}
+
static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
ImBuf * ibuf;
int frameFinished;
@@ -692,6 +804,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
int64_t pts_to_search = 0;
int pos_found = 1;
int filter_y = 0;
+ int seek_by_bytes= 0;
+ int preseek_count = 0;
if (anim == 0) return (0);
@@ -724,6 +838,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
}
}
+ seek_by_bytes = !!(anim->pFormatCtx->iformat->flags & AVFMT_TS_DISCONT);
+
if (position != anim->curposition + 1) {
#ifdef FFMPEG_OLD_FRAME_RATE
double frame_rate =
@@ -737,21 +853,41 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
double time_base =
av_q2d(anim->pFormatCtx->streams[anim->videoStream]
->time_base);
- long long pos = (long long) (position - anim->preseek)
- * AV_TIME_BASE / frame_rate;
+ long long pos;
long long st_time = anim->pFormatCtx
->streams[anim->videoStream]->start_time;
+ int ret;
- if (pos < 0) {
- pos = 0;
- }
+ if (seek_by_bytes) {
+ pos = position - anim->preseek;
+ if (pos < 0) {
+ pos = 0;
+ }
+ preseek_count = position - pos;
- if (st_time != AV_NOPTS_VALUE) {
- pos += st_time * AV_TIME_BASE * time_base;
+ pos *= anim->pFormatCtx->bit_rate / frame_rate;
+ pos /= 8;
+ } else {
+ pos = (long long) (position - anim->preseek)
+ * AV_TIME_BASE / frame_rate;
+ if (pos < 0) {
+ pos = 0;
+ }
+
+ if (st_time != AV_NOPTS_VALUE) {
+ pos += st_time * AV_TIME_BASE * time_base;
+ }
}
- av_seek_frame(anim->pFormatCtx, -1,
- pos, AVSEEK_FLAG_BACKWARD);
+ ret = av_seek_frame(anim->pFormatCtx, -1,
+ pos,
+ AVSEEK_FLAG_BACKWARD | (
+ seek_by_bytes
+ ? AVSEEK_FLAG_ANY
+ | AVSEEK_FLAG_BYTE : 0));
+ if (ret < 0) {
+ fprintf(stderr, "error while seeking: %d\n", ret);
+ }
pts_to_search = (long long)
(((double) position) / time_base / frame_rate);
@@ -769,132 +905,28 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
anim->pFrame, &frameFinished,
packet.data, packet.size);
- if (frameFinished && !pos_found) {
- if (packet.dts >= pts_to_search) {
- pos_found = 1;
- anim->curposition = position;
- }
- }
-
- if(frameFinished && pos_found == 1) {
- AVFrame * input = anim->pFrame;
-
- /* This means the data wasnt read properly,
- this check stops crashing */
- if (input->data[0]==0 && input->data[1]==0
- && input->data[2]==0 && input->data[3]==0){
- av_free_packet(&packet);
- break;
- }
-
- 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) {
- filter_y = 1;
- } else {
- input = anim->pFrameDeinterlaced;
- }
- }
+ if (seek_by_bytes && preseek_count > 0) {
+ preseek_count--;
+ }
- if (ENDIAN_ORDER == B_ENDIAN) {
- int * dstStride
- = anim->pFrameRGB->linesize;
- uint8_t** dst = anim->pFrameRGB->data;
- int dstStride2[4]
- = { dstStride[0], 0, 0, 0 };
- uint8_t* dst2[4]= {
- dst[0], 0, 0, 0 };
- int x,y,h,w;
- unsigned char* bottom;
- unsigned char* top;
-
- sws_scale(anim->img_convert_ctx,
- (const uint8_t * const *)input->data,
- input->linesize,
- 0,
- anim->pCodecCtx->height,
- dst2,
- dstStride2);
-
- /* workaround: sws_scale
- sets alpha = 0 and compensate
- for altivec-bugs and flipy... */
-
- bottom = (unsigned char*) ibuf->rect;
- top = bottom
- + ibuf->x * (ibuf->y-1) * 4;
-
- h = (ibuf->y + 1) / 2;
- w = ibuf->x;
-
- for (y = 0; y < h; y++) {
- unsigned char tmp[4];
- unsigned int * tmp_l =
- (unsigned int*) tmp;
- tmp[3] = 0xff;
-
- for (x = 0; x < w; x++) {
- tmp[0] = bottom[0];
- tmp[1] = bottom[1];
- tmp[2] = bottom[2];
-
- bottom[0] = top[0];
- bottom[1] = top[1];
- bottom[2] = top[2];
- bottom[3] = 0xff;
-
- *(unsigned int*) top
- = *tmp_l;
-
- bottom +=4;
- top += 4;
- }
- top -= 8 * w;
+ if (frameFinished && !pos_found) {
+ if (seek_by_bytes) {
+ if (!preseek_count) {
+ pos_found = 1;
+ anim->curposition = position;
}
-
- av_free_packet(&packet);
- break;
} else {
- int * dstStride
- = anim->pFrameRGB->linesize;
- uint8_t** dst = anim->pFrameRGB->data;
- int dstStride2[4]
- = { -dstStride[0], 0, 0, 0 };
- uint8_t* dst2[4]= {
- dst[0]
- + (anim->y - 1)*dstStride[0],
- 0, 0, 0 };
- int i;
- unsigned char* r;
-
- sws_scale(anim->img_convert_ctx,
- (const uint8_t * const *)input->data,
- input->linesize,
- 0,
- anim->pCodecCtx->height,
- dst2,
- dstStride2);
-
- /* workaround: sws_scale
- sets alpha = 0... */
-
- r = (unsigned char*) ibuf->rect;
-
- for (i = 0; i < ibuf->x * ibuf->y;i++){
- r[3] = 0xff;
- r+=4;
+ if (packet.dts >= pts_to_search) {
+ pos_found = 1;
+ anim->curposition = position;
}
-
- av_free_packet(&packet);
- break;
}
+ }
+
+ if(frameFinished && pos_found == 1) {
+ ffmpeg_postprocess(anim, ibuf, &filter_y);
+ av_free_packet(&packet);
+ break;
}
}