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_movie.c')
-rw-r--r--source/blender/imbuf/intern/anim_movie.c176
1 files changed, 39 insertions, 137 deletions
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 6a05b681c88..38dbb9bfc47 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -504,11 +504,6 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
#ifdef WITH_FFMPEG
-BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim)
-{
- return (anim->x & 31) != 0;
-}
-
static int startffmpeg(struct anim *anim)
{
int i, video_stream_index;
@@ -707,23 +702,20 @@ static int startffmpeg(struct anim *anim)
anim->pFrameComplete = false;
anim->pFrameDeinterlaced = av_frame_alloc();
anim->pFrameRGB = av_frame_alloc();
+ anim->pFrameRGB->format = AV_PIX_FMT_RGBA;
+ anim->pFrameRGB->width = anim->x;
+ anim->pFrameRGB->height = anim->y;
- if (need_aligned_ffmpeg_buffer(anim)) {
- anim->pFrameRGB->format = AV_PIX_FMT_RGBA;
- anim->pFrameRGB->width = anim->x;
- anim->pFrameRGB->height = anim->y;
-
- if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) {
- fprintf(stderr, "Could not allocate frame data.\n");
- avcodec_free_context(&anim->pCodecCtx);
- avformat_close_input(&anim->pFormatCtx);
- av_packet_free(&anim->cur_packet);
- av_frame_free(&anim->pFrameRGB);
- av_frame_free(&anim->pFrameDeinterlaced);
- av_frame_free(&anim->pFrame);
- anim->pCodecCtx = NULL;
- return -1;
- }
+ if (av_frame_get_buffer(anim->pFrameRGB, 0) < 0) {
+ fprintf(stderr, "Could not allocate frame data.\n");
+ avcodec_free_context(&anim->pCodecCtx);
+ avformat_close_input(&anim->pFormatCtx);
+ av_packet_free(&anim->cur_packet);
+ av_frame_free(&anim->pFrameRGB);
+ av_frame_free(&anim->pFrameDeinterlaced);
+ av_frame_free(&anim->pFrame);
+ anim->pCodecCtx = NULL;
+ return -1;
}
if (av_image_get_buffer_size(AV_PIX_FMT_RGBA, anim->x, anim->y, 1) != anim->x * anim->y * 4) {
@@ -851,92 +843,26 @@ static void ffmpeg_postprocess(struct anim *anim)
}
}
- if (!need_aligned_ffmpeg_buffer(anim)) {
- 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)
- /* Scale and flip image over Y axis in one go, using negative strides.
- * This doesn't work with ARM/PowerPC though and may be misusing the API.
- * Limit it x86_64 where it appears to work.
- * http://trac.ffmpeg.org/ticket/9060 */
- int *dstStride = anim->pFrameRGB->linesize;
- uint8_t **dst = anim->pFrameRGB->data;
- const int dstStride2[4] = {-dstStride[0], 0, 0, 0};
- uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0};
-
- sws_scale(anim->img_convert_ctx,
- (const uint8_t *const *)input->data,
- input->linesize,
- 0,
- anim->y,
- dst2,
- dstStride2);
-# else
- /* Scale with swscale. */
- int *dstStride = anim->pFrameRGB->linesize;
- uint8_t **dst = anim->pFrameRGB->data;
- const 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->y,
- dst2,
- dstStride2);
-
- /* Flip destination image buffer over Y axis. */
- bottom = (unsigned char *)dst[0];
- top = bottom + anim->x * (anim->y - 1) * 4;
-
- h = (anim->y + 1) / 2;
- w = anim->x;
-
- for (y = 0; y < h; y++) {
- unsigned char tmp[4];
- unsigned int *tmp_l = (unsigned int *)tmp;
-
- for (x = 0; x < w; x++) {
- tmp[0] = bottom[0];
- tmp[1] = bottom[1];
- tmp[2] = bottom[2];
- tmp[3] = bottom[3];
-
- bottom[0] = top[0];
- bottom[1] = top[1];
- bottom[2] = top[2];
- bottom[3] = top[3];
-
- *(unsigned int *)top = *tmp_l;
-
- bottom += 4;
- top += 4;
- }
- top -= 8 * w;
- }
-# endif
-
- if (need_aligned_ffmpeg_buffer(anim)) {
- uint8_t *buf_src = anim->pFrameRGB->data[0];
- uint8_t *buf_dst = (uint8_t *)ibuf->rect;
- for (int y = 0; y < anim->y; y++) {
- memcpy(buf_dst, buf_src, anim->x * 4);
- buf_dst += anim->x * 4;
- buf_src += anim->pFrameRGB->linesize[0];
- }
- }
-
+ anim->pFrameRGB->data,
+ anim->pFrameRGB->linesize);
+
+ /* Copy the valid bytes from the aligned buffer vertically flipped into ImBuf */
+ int aligned_stride = anim->pFrameRGB->linesize[0];
+ const uint8_t *const src[4] = {
+ anim->pFrameRGB->data[0] + (anim->y - 1) * aligned_stride, 0, 0, 0};
+ /* NOTE: Negative linesize is used to copy and flip image at once with function
+ * `av_image_copy_to_buffer`. This could cause issues in future and image may need to be flipped
+ * explicitly. */
+ const int src_linesize[4] = {-anim->pFrameRGB->linesize[0], 0, 0, 0};
+ int dst_size = av_image_get_buffer_size(
+ anim->pFrameRGB->format, anim->pFrameRGB->width, anim->pFrameRGB->height, 1);
+ av_image_copy_to_buffer(
+ (uint8_t *)ibuf->rect, dst_size, src, src_linesize, AV_PIX_FMT_RGBA, anim->x, anim->y, 1);
if (filter_y) {
IMB_filtery(ibuf);
}
@@ -1067,21 +993,23 @@ static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
return false;
}
-static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
+static double ffmpeg_steps_per_frame_get(struct anim *anim)
{
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
- AVRational frame_rate = v_st->r_frame_rate;
AVRational time_base = v_st->time_base;
- double steps_per_frame = (double)(frame_rate.den * time_base.den) /
- (double)(frame_rate.num * time_base.num);
+ AVRational frame_rate = av_guess_frame_rate(anim->pFormatCtx, v_st, NULL);
+ return av_q2d(av_inv_q(av_mul_q(frame_rate, time_base)));
+ ;
+}
+
+static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
+{
/* Step back half a frame position to make sure that we get the requested
* frame and not the one after it. This is a workaround as ffmpeg will
* sometimes not seek to a frame after the requested pts even if
* AVSEEK_FLAG_BACKWARD is specified.
*/
- int64_t pts = pts_to_search - (steps_per_frame / 2);
-
- return pts;
+ return pts_to_search - (ffmpeg_steps_per_frame_get(anim) / 2);
}
/* This gives us an estimate of which pts our requested frame will have.
@@ -1100,13 +1028,8 @@ static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
else {
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
int64_t start_pts = v_st->start_time;
- AVRational frame_rate = v_st->r_frame_rate;
- AVRational time_base = v_st->time_base;
-
- double steps_per_frame = (double)(frame_rate.den * time_base.den) /
- (double)(frame_rate.num * time_base.num);
- pts_to_search = round(position * steps_per_frame);
+ pts_to_search = round(position * ffmpeg_steps_per_frame_get(anim));
if (start_pts != AV_NOPTS_VALUE) {
pts_to_search += start_pts;
@@ -1196,13 +1119,6 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim,
int64_t *requested_pts,
int64_t pts_to_search)
{
- AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
- AVRational frame_rate = v_st->r_frame_rate;
- AVRational time_base = v_st->time_base;
-
- double steps_per_frame = (double)(frame_rate.den * time_base.den) /
- (double)(frame_rate.num * time_base.num);
-
int64_t current_pts = *requested_pts;
int64_t offset = 0;
@@ -1210,7 +1126,7 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim,
/* Step backward frame by frame until we find the key frame we are looking for. */
while (current_pts != 0) {
- current_pts = *requested_pts - (int64_t)round(offset * steps_per_frame);
+ current_pts = *requested_pts - (int64_t)round(offset * ffmpeg_steps_per_frame_get(anim));
current_pts = MAX2(current_pts, 0);
/* Seek to timestamp. */
@@ -1482,20 +1398,6 @@ static void free_anim_ffmpeg(struct anim *anim)
av_packet_free(&anim->cur_packet);
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.
- */
- 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);