Changeset View
Changeset View
Standalone View
Standalone View
source/blender/imbuf/intern/anim_movie.c
| Show First 20 Lines • Show All 499 Lines • ▼ Show 20 Lines | |||||
| #ifdef WITH_FFMPEG | #ifdef WITH_FFMPEG | ||||
| BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim) | BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim) | ||||
| { | { | ||||
| return (anim->x & 31) != 0; | return (anim->x & 31) != 0; | ||||
| } | } | ||||
| IMB_Downscale downscale_factor_to_downscale_index(const float downscale_factor) | |||||
| { | |||||
| if (downscale_factor > 32.0f) { | |||||
| return IMB_DOWNSCALE_32X; | |||||
| } | |||||
| if (downscale_factor <= 1.0f) { | |||||
| return IMB_DOWNSCALE_NONE; | |||||
| } | |||||
| return round_fl_to_int(log2(downscale_factor)); | |||||
| } | |||||
| int downscale_index_to_downscale_factor(const IMB_Downscale downscale_index) | |||||
| { | |||||
| switch (downscale_index) { | |||||
| case IMB_DOWNSCALE_2X: | |||||
| return 2; | |||||
| case IMB_DOWNSCALE_4X: | |||||
| return 4; | |||||
| case IMB_DOWNSCALE_8X: | |||||
| return 8; | |||||
| case IMB_DOWNSCALE_16X: | |||||
| return 16; | |||||
| case IMB_DOWNSCALE_32X: | |||||
| return 32; | |||||
| default: | |||||
| return 1; | |||||
| } | |||||
| } | |||||
| static int ffmpeg_sws_context_alloc(struct anim *anim, const IMB_Downscale downscale_index) | |||||
| { | |||||
| const int scale_factor = downscale_index_to_downscale_factor(downscale_index); | |||||
| anim->img_convert_ctx[downscale_index] = sws_getContext(anim->x, | |||||
| anim->y, | |||||
| anim->pCodecCtx->pix_fmt, | |||||
| anim->x / scale_factor, | |||||
| anim->y / scale_factor, | |||||
| AV_PIX_FMT_RGBA, | |||||
| SWS_FAST_BILINEAR | SWS_PRINT_INFO | | |||||
| SWS_FULL_CHR_H_INT, | |||||
| NULL, | |||||
| NULL, | |||||
| NULL); | |||||
| if (!anim->img_convert_ctx[downscale_index]) { | |||||
| fprintf(stderr, "Can't transform color space??? Bailing out...\n"); | |||||
| avcodec_close(anim->pCodecCtx); | |||||
| avformat_close_input(&anim->pFormatCtx); | |||||
| av_frame_free(&anim->pFrameRGB); | |||||
| av_frame_free(&anim->pFrameDeinterlaced); | |||||
| av_frame_free(&anim->pFrame); | |||||
| anim->pCodecCtx = NULL; | |||||
| return -1; | |||||
| } | |||||
| # ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT | |||||
| /* The following for color space determination */ | |||||
| int srcRange, dstRange, brightness, contrast, saturation; | |||||
| int *table; | |||||
| const int *inv_table; | |||||
| /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ | |||||
| if (!sws_getColorspaceDetails(anim->img_convert_ctx[downscale_index], | |||||
| (int **)&inv_table, | |||||
| &srcRange, | |||||
| &table, | |||||
| &dstRange, | |||||
| &brightness, | |||||
| &contrast, | |||||
| &saturation)) { | |||||
| srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; | |||||
| inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); | |||||
| if (sws_setColorspaceDetails(anim->img_convert_ctx[downscale_index], | |||||
| (int *)inv_table, | |||||
| srcRange, | |||||
| table, | |||||
| dstRange, | |||||
| brightness, | |||||
| contrast, | |||||
| saturation)) { | |||||
| fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); | |||||
| } | |||||
| } | |||||
| else { | |||||
| fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); | |||||
| } | |||||
| # endif | |||||
| return 0; | |||||
| } | |||||
| static int startffmpeg(struct anim *anim) | static int startffmpeg(struct anim *anim) | ||||
| { | { | ||||
| int i, video_stream_index; | int i, video_stream_index; | ||||
| AVCodec *pCodec; | AVCodec *pCodec; | ||||
| AVFormatContext *pFormatCtx = NULL; | AVFormatContext *pFormatCtx = NULL; | ||||
| AVCodecContext *pCodecCtx; | AVCodecContext *pCodecCtx; | ||||
| AVRational frame_rate; | AVRational frame_rate; | ||||
| AVStream *video_stream; | AVStream *video_stream; | ||||
| int frs_num; | int frs_num; | ||||
| double frs_den; | double frs_den; | ||||
| int streamcount; | 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) { | if (anim == NULL) { | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| streamcount = anim->streamindex; | streamcount = anim->streamindex; | ||||
| if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) { | if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) { | ||||
| return -1; | return -1; | ||||
| ▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | static int startffmpeg(struct anim *anim) | ||||
| if (pCodecCtx->has_b_frames) { | if (pCodecCtx->has_b_frames) { | ||||
| anim->preseek = 25; /* FIXME: detect gopsize ... */ | anim->preseek = 25; /* FIXME: detect gopsize ... */ | ||||
| } | } | ||||
| else { | else { | ||||
| anim->preseek = 0; | anim->preseek = 0; | ||||
| } | } | ||||
| anim->img_convert_ctx = sws_getContext(anim->x, | for (IMB_Downscale index = 0; index < IMB_DOWNSCALE_MAX_SLOT; index++) { | ||||
| anim->y, | int error = ffmpeg_sws_context_alloc(anim, index); | ||||
| anim->pCodecCtx->pix_fmt, | if (error != 0) { | ||||
| anim->x, | return error; | ||||
| anim->y, | |||||
| AV_PIX_FMT_RGBA, | |||||
| SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT, | |||||
| NULL, | |||||
| NULL, | |||||
| NULL); | |||||
| if (!anim->img_convert_ctx) { | |||||
| fprintf(stderr, "Can't transform color space??? Bailing out...\n"); | |||||
| avcodec_close(anim->pCodecCtx); | |||||
| avformat_close_input(&anim->pFormatCtx); | |||||
| av_frame_free(&anim->pFrameRGB); | |||||
| av_frame_free(&anim->pFrameDeinterlaced); | |||||
| av_frame_free(&anim->pFrame); | |||||
| anim->pCodecCtx = NULL; | |||||
| 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, | |||||
| &srcRange, | |||||
| &table, | |||||
| &dstRange, | |||||
| &brightness, | |||||
| &contrast, | |||||
| &saturation)) { | |||||
| srcRange = srcRange || anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG; | |||||
| inv_table = sws_getCoefficients(anim->pCodecCtx->colorspace); | |||||
| if (sws_setColorspaceDetails(anim->img_convert_ctx, | |||||
| (int *)inv_table, | |||||
| srcRange, | |||||
| table, | |||||
| dstRange, | |||||
| brightness, | |||||
| contrast, | |||||
| saturation)) { | |||||
| fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); | |||||
| } | |||||
| } | } | ||||
| else { | |||||
| fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); | |||||
| } | } | ||||
| # endif | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* postprocess the image in anim->pFrame and do color conversion | /* postprocess the image in anim->pFrame and do color conversion | ||||
| * and deinterlacing stuff. | * and deinterlacing stuff. | ||||
| * | * | ||||
| * Output is anim->last_frame | * Output is anim->last_frame | ||||
| */ | */ | ||||
| static void ffmpeg_postprocess(struct anim *anim) | static void ffmpeg_postprocess(struct anim *anim, const IMB_Downscale downscale_index) | ||||
| { | { | ||||
| AVFrame *input = anim->pFrame; | AVFrame *input = anim->pFrame; | ||||
| ImBuf *ibuf = anim->last_frame; | ImBuf *ibuf = anim->last_frame; | ||||
| int filter_y = 0; | int filter_y = 0; | ||||
| if (!anim->pFrameComplete) { | if (!anim->pFrameComplete) { | ||||
| return; | return; | ||||
| } | } | ||||
| Show All 27 Lines | else { | ||||
| input = anim->pFrameDeinterlaced; | input = anim->pFrameDeinterlaced; | ||||
| } | } | ||||
| } | } | ||||
| if (!need_aligned_ffmpeg_buffer(anim)) { | if (!need_aligned_ffmpeg_buffer(anim)) { | ||||
| avpicture_fill((AVPicture *)anim->pFrameRGB, | avpicture_fill((AVPicture *)anim->pFrameRGB, | ||||
| (unsigned char *)ibuf->rect, | (unsigned char *)ibuf->rect, | ||||
| AV_PIX_FMT_RGBA, | AV_PIX_FMT_RGBA, | ||||
| anim->x, | ibuf->x, | ||||
| anim->y); | ibuf->y); | ||||
| } | } | ||||
| if (ENDIAN_ORDER == B_ENDIAN) { | if (ENDIAN_ORDER == B_ENDIAN) { | ||||
| int *dstStride = anim->pFrameRGB->linesize; | int *dstStride = anim->pFrameRGB->linesize; | ||||
| uint8_t **dst = anim->pFrameRGB->data; | uint8_t **dst = anim->pFrameRGB->data; | ||||
| const int dstStride2[4] = {dstStride[0], 0, 0, 0}; | const int dstStride2[4] = {dstStride[0], 0, 0, 0}; | ||||
| uint8_t *dst2[4] = {dst[0], 0, 0, 0}; | uint8_t *dst2[4] = {dst[0], 0, 0, 0}; | ||||
| int x, y, h, w; | int x, y, h, w; | ||||
| unsigned char *bottom; | unsigned char *bottom; | ||||
| unsigned char *top; | unsigned char *top; | ||||
| sws_scale(anim->img_convert_ctx, | sws_scale(anim->img_convert_ctx[downscale_index], | ||||
| (const uint8_t *const *)input->data, | (const uint8_t *const *)input->data, | ||||
| input->linesize, | input->linesize, | ||||
| 0, | 0, | ||||
| anim->y, | anim->y, | ||||
| dst2, | dst2, | ||||
| dstStride2); | dstStride2); | ||||
| bottom = (unsigned char *)ibuf->rect; | bottom = (unsigned char *)ibuf->rect; | ||||
| Show All 24 Lines | for (y = 0; y < h; y++) { | ||||
| } | } | ||||
| top -= 8 * w; | top -= 8 * w; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| int *dstStride = anim->pFrameRGB->linesize; | int *dstStride = anim->pFrameRGB->linesize; | ||||
| uint8_t **dst = anim->pFrameRGB->data; | uint8_t **dst = anim->pFrameRGB->data; | ||||
| const int dstStride2[4] = {-dstStride[0], 0, 0, 0}; | const int dstStride2[4] = {-dstStride[0], 0, 0, 0}; | ||||
| uint8_t *dst2[4] = {dst[0] + (anim->y - 1) * dstStride[0], 0, 0, 0}; | uint8_t *dst2[4] = {dst[0] + (ibuf->y - 1) * dstStride[0], 0, 0, 0}; | ||||
| sws_scale(anim->img_convert_ctx, | sws_scale(anim->img_convert_ctx[downscale_index], | ||||
| (const uint8_t *const *)input->data, | (const uint8_t *const *)input->data, | ||||
| input->linesize, | input->linesize, | ||||
| 0, | 0, | ||||
| anim->y, | anim->y, | ||||
| dst2, | dst2, | ||||
| dstStride2); | dstStride2); | ||||
| } | } | ||||
| if (need_aligned_ffmpeg_buffer(anim)) { | if (need_aligned_ffmpeg_buffer(anim)) { | ||||
| uint8_t *src = anim->pFrameRGB->data[0]; | uint8_t *src = anim->pFrameRGB->data[0]; | ||||
| uint8_t *dst = (uint8_t *)ibuf->rect; | uint8_t *dst = (uint8_t *)ibuf->rect; | ||||
| for (int y = 0; y < anim->y; y++) { | for (int y = 0; y < ibuf->y; y++) { | ||||
| memcpy(dst, src, anim->x * 4); | memcpy(dst, src, ibuf->x * 4); | ||||
| dst += anim->x * 4; | dst += ibuf->x * 4; | ||||
| src += anim->pFrameRGB->linesize[0]; | src += anim->pFrameRGB->linesize[0]; | ||||
| } | } | ||||
| } | } | ||||
| if (filter_y) { | if (filter_y) { | ||||
| IMB_filtery(ibuf); | IMB_filtery(ibuf); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | while (*p) { | ||||
| if (match_format(*p++, pFormatCtx)) { | if (match_format(*p++, pFormatCtx)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Type tc) | static ImBuf *ffmpeg_fill_ibuf(struct anim *anim, const IMB_Downscale downscale_index) | ||||
| { | |||||
| const int scale_factor = downscale_index_to_downscale_factor(downscale_index); | |||||
| const int width = anim->x / scale_factor; | |||||
| const int height = anim->y / scale_factor; | |||||
| /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash | |||||
| * when destination buffer is not properly aligned. For example, this happens | |||||
| * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is | |||||
| * still best to avoid crash. | |||||
| * | |||||
| * This is achieved by using own allocation call rather than relying on | |||||
| * IMB_allocImBuf() to do so since the IMB_allocImBuf() is not guaranteed | |||||
| * to perform aligned allocation. | |||||
| * | |||||
| * In theory this could give better performance, since SIMD operations on | |||||
| * aligned data are usually faster. | |||||
| * | |||||
| * Note that even though sometimes vertical flip is required it does not | |||||
| * affect on alignment of data passed to sws_scale because if the X dimension | |||||
| * is not 32 byte aligned special intermediate buffer is allocated. | |||||
| * | |||||
| * The issue was reported to FFmpeg under ticket #8747 in the FFmpeg tracker | |||||
| * and is fixed in the newer versions than 4.3.1. */ | |||||
| IMB_freeImBuf(anim->last_frame); | |||||
| anim->last_frame = IMB_allocImBuf(width, height, 32, 0); | |||||
| anim->last_frame->rect = MEM_mallocN_aligned((size_t)4 * width * height, 32, "ffmpeg ibuf"); | |||||
| anim->last_frame->mall |= IB_rect; | |||||
| anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); | |||||
| ffmpeg_postprocess(anim, downscale_index); | |||||
| IMB_refImBuf(anim->last_frame); | |||||
| return anim->last_frame; | |||||
| } | |||||
| static ImBuf *ffmpeg_fetchibuf(struct anim *anim, | |||||
| int position, | |||||
| IMB_Timecode_Type tc, | |||||
| const IMB_Downscale downscale_index) | |||||
| { | { | ||||
| int64_t pts_to_search = 0; | int64_t pts_to_search = 0; | ||||
| double frame_rate; | double frame_rate; | ||||
| double pts_time_base; | double pts_time_base; | ||||
| long long st_time; | long long st_time; | ||||
| struct anim_index *tc_index = 0; | struct anim_index *tc_index = 0; | ||||
| AVStream *v_st; | AVStream *v_st; | ||||
| int new_frame_index = 0; /* To quiet gcc barking... */ | int new_frame_index = 0; /* To quiet gcc barking... */ | ||||
| Show All 34 Lines | av_log(anim->pFormatCtx, | ||||
| "FETCH: looking for PTS=%lld " | "FETCH: looking for PTS=%lld " | ||||
| "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", | "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", | ||||
| (long long int)pts_to_search, | (long long int)pts_to_search, | ||||
| pts_time_base, | pts_time_base, | ||||
| frame_rate, | frame_rate, | ||||
| st_time); | st_time); | ||||
| if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) { | if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) { | ||||
| if (anim->last_downscale_index != downscale_index) { | |||||
| return ffmpeg_fill_ibuf(anim, downscale_index); | |||||
| } | |||||
| av_log(anim->pFormatCtx, | av_log(anim->pFormatCtx, | ||||
| AV_LOG_DEBUG, | AV_LOG_DEBUG, | ||||
| "FETCH: frame repeat: last: %lld next: %lld\n", | "FETCH: frame repeat: last: %lld next: %lld\n", | ||||
| (long long int)anim->last_pts, | (long long int)anim->last_pts, | ||||
| (long long int)anim->next_pts); | (long long int)anim->next_pts); | ||||
| IMB_refImBuf(anim->last_frame); | IMB_refImBuf(anim->last_frame); | ||||
| anim->curposition = position; | anim->curposition = position; | ||||
| return anim->last_frame; | return anim->last_frame; | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | static ImBuf *ffmpeg_fetchibuf(struct anim *anim, | ||||
| else if (position == 0 && anim->curposition == -1) { | else if (position == 0 && anim->curposition == -1) { | ||||
| /* first frame without seeking special case... */ | /* first frame without seeking special case... */ | ||||
| ffmpeg_decode_video_frame(anim); | ffmpeg_decode_video_frame(anim); | ||||
| } | } | ||||
| else { | else { | ||||
| av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n"); | av_log(anim->pFormatCtx, AV_LOG_DEBUG, "FETCH: no seek necessary, just continue...\n"); | ||||
| } | } | ||||
| IMB_freeImBuf(anim->last_frame); | ffmpeg_fill_ibuf(anim, downscale_index); | ||||
| /* Certain versions of FFmpeg have a bug in libswscale which ends up in crash | |||||
| * when destination buffer is not properly aligned. For example, this happens | |||||
| * in FFmpeg 4.3.1. It got fixed later on, but for compatibility reasons is | |||||
| * still best to avoid crash. | |||||
| * | |||||
| * This is achieved by using own allocation call rather than relying on | |||||
| * IMB_allocImBuf() to do so since the IMB_allocImBuf() is not guaranteed | |||||
| * to perform aligned allocation. | |||||
| * | |||||
| * In theory this could give better performance, since SIMD operations on | |||||
| * aligned data are usually faster. | |||||
| * | |||||
| * Note that even though sometimes vertical flip is required it does not | |||||
| * affect on alignment of data passed to sws_scale because if the X dimension | |||||
| * is not 32 byte aligned special intermediate buffer is allocated. | |||||
| * | |||||
| * The issue was reported to FFmpeg under ticket #8747 in the FFmpeg tracker | |||||
| * and is fixed in the newer versions than 4.3.1. */ | |||||
| anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, 0); | |||||
| anim->last_frame->rect = MEM_mallocN_aligned((size_t)4 * anim->x * anim->y, 32, "ffmpeg ibuf"); | |||||
| anim->last_frame->mall |= IB_rect; | |||||
| anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); | |||||
| ffmpeg_postprocess(anim); | |||||
| anim->last_pts = anim->next_pts; | anim->last_pts = anim->next_pts; | ||||
| ffmpeg_decode_video_frame(anim); | ffmpeg_decode_video_frame(anim); | ||||
| anim->curposition = position; | anim->curposition = position; | ||||
| IMB_refImBuf(anim->last_frame); | |||||
| return anim->last_frame; | return anim->last_frame; | ||||
| } | } | ||||
| static void free_anim_ffmpeg(struct anim *anim) | static void free_anim_ffmpeg(struct anim *anim) | ||||
| { | { | ||||
| if (anim == NULL) { | if (anim == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| Show All 15 Lines | if (!need_aligned_ffmpeg_buffer(anim)) { | ||||
| * frame shares the same buffer as temporary ImBuf. In this case we | * frame shares the same buffer as temporary ImBuf. In this case we | ||||
| * should not free the buffer when freeing the FFmpeg buffer. | * should not free the buffer when freeing the FFmpeg buffer. | ||||
| */ | */ | ||||
| avpicture_fill((AVPicture *)anim->pFrameRGB, NULL, AV_PIX_FMT_RGBA, anim->x, anim->y); | avpicture_fill((AVPicture *)anim->pFrameRGB, NULL, AV_PIX_FMT_RGBA, anim->x, anim->y); | ||||
| } | } | ||||
| av_frame_free(&anim->pFrameRGB); | av_frame_free(&anim->pFrameRGB); | ||||
| av_frame_free(&anim->pFrameDeinterlaced); | av_frame_free(&anim->pFrameDeinterlaced); | ||||
| sws_freeContext(anim->img_convert_ctx); | for (IMB_Downscale index = 0; index < IMB_DOWNSCALE_MAX_SLOT; index++) { | ||||
| if (anim->img_convert_ctx[index] != NULL) { | |||||
| sws_freeContext(anim->img_convert_ctx[index]); | |||||
| } | |||||
| } | |||||
| IMB_freeImBuf(anim->last_frame); | IMB_freeImBuf(anim->last_frame); | ||||
| if (anim->next_packet.stream_index != -1) { | if (anim->next_packet.stream_index != -1) { | ||||
| av_free_packet(&anim->next_packet); | av_free_packet(&anim->next_packet); | ||||
| } | } | ||||
| } | } | ||||
| anim->duration_in_frames = 0; | anim->duration_in_frames = 0; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | #endif | ||||
| return ibuf; | return ibuf; | ||||
| } | } | ||||
| struct ImBuf *IMB_anim_previewframe(struct anim *anim) | struct ImBuf *IMB_anim_previewframe(struct anim *anim) | ||||
| { | { | ||||
| struct ImBuf *ibuf = NULL; | struct ImBuf *ibuf = NULL; | ||||
| int position = 0; | int position = 0; | ||||
| ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); | ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE, IMB_DOWNSCALE_NONE); | ||||
| if (ibuf) { | if (ibuf) { | ||||
| IMB_freeImBuf(ibuf); | IMB_freeImBuf(ibuf); | ||||
| position = anim->duration_in_frames / 2; | position = anim->duration_in_frames / 2; | ||||
| ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, IMB_PROXY_NONE); | ibuf = IMB_anim_absolute(anim, position, IMB_TC_NONE, IMB_PROXY_NONE, IMB_DOWNSCALE_NONE); | ||||
| } | } | ||||
| return ibuf; | return ibuf; | ||||
| } | } | ||||
| struct ImBuf *IMB_anim_absolute(struct anim *anim, | struct ImBuf *IMB_anim_absolute(struct anim *anim, | ||||
| int position, | int position, | ||||
| IMB_Timecode_Type tc, | IMB_Timecode_Type tc, | ||||
| IMB_Proxy_Size preview_size) | IMB_Proxy_Size preview_size, | ||||
| const IMB_Downscale downscale_index) | |||||
| { | { | ||||
| struct ImBuf *ibuf = NULL; | struct ImBuf *ibuf = NULL; | ||||
| char head[256], tail[256]; | char head[256], tail[256]; | ||||
| unsigned short digits; | unsigned short digits; | ||||
| int pic; | int pic; | ||||
| int filter_y; | int filter_y; | ||||
| if (anim == NULL) { | if (anim == NULL) { | ||||
| return NULL; | return NULL; | ||||
| Show All 20 Lines | if (preview_size == IMB_PROXY_NONE) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| struct anim *proxy = IMB_anim_open_proxy(anim, preview_size); | struct anim *proxy = IMB_anim_open_proxy(anim, preview_size); | ||||
| if (proxy) { | if (proxy) { | ||||
| position = IMB_anim_index_get_frame_index(anim, tc, position); | position = IMB_anim_index_get_frame_index(anim, tc, position); | ||||
| return IMB_anim_absolute(proxy, position, IMB_TC_NONE, IMB_PROXY_NONE); | return IMB_anim_absolute(proxy, position, IMB_TC_NONE, IMB_PROXY_NONE, downscale_index); | ||||
| } | } | ||||
| } | } | ||||
| switch (anim->curtype) { | switch (anim->curtype) { | ||||
| case ANIM_SEQUENCE: | case ANIM_SEQUENCE: | ||||
| pic = an_stringdec(anim->first, head, tail, &digits); | pic = an_stringdec(anim->first, head, tail, &digits); | ||||
| pic += position; | pic += position; | ||||
| an_stringenc(anim->name, head, tail, digits, pic); | an_stringenc(anim->name, head, tail, digits, pic); | ||||
| Show All 14 Lines | case ANIM_AVI: | ||||
| ibuf = avi_fetchibuf(anim, position); | ibuf = avi_fetchibuf(anim, position); | ||||
| if (ibuf) { | if (ibuf) { | ||||
| anim->curposition = position; | anim->curposition = position; | ||||
| } | } | ||||
| break; | break; | ||||
| #endif | #endif | ||||
| #ifdef WITH_FFMPEG | #ifdef WITH_FFMPEG | ||||
| case ANIM_FFMPEG: | case ANIM_FFMPEG: | ||||
| ibuf = ffmpeg_fetchibuf(anim, position, tc); | ibuf = ffmpeg_fetchibuf(anim, position, tc, downscale_index); | ||||
| if (ibuf) { | if (ibuf) { | ||||
| anim->curposition = position; | anim->curposition = position; | ||||
| anim->last_downscale_index = downscale_index; | |||||
| } | } | ||||
| filter_y = 0; /* done internally */ | filter_y = 0; /* done internally */ | ||||
| break; | break; | ||||
| #endif | #endif | ||||
| } | } | ||||
| if (ibuf) { | if (ibuf) { | ||||
| if (filter_y) { | if (filter_y) { | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | |||||
| int IMB_anim_get_preseek(struct anim *anim) | int IMB_anim_get_preseek(struct anim *anim) | ||||
| { | { | ||||
| return anim->preseek; | return anim->preseek; | ||||
| } | } | ||||
| int IMB_anim_get_image_width(struct anim *anim) | int IMB_anim_get_image_width(struct anim *anim) | ||||
| { | { | ||||
| /* Anim not initialized - initialize it. */ | |||||
| if (anim->curtype == 0) { | |||||
| startffmpeg(anim); | |||||
| } | |||||
| return anim->x; | return anim->x; | ||||
| } | } | ||||
| int IMB_anim_get_image_height(struct anim *anim) | int IMB_anim_get_image_height(struct anim *anim) | ||||
| { | { | ||||
| /* Anim not initialized - initialize it. */ | |||||
| if (anim->curtype == 0) { | |||||
| startffmpeg(anim); | |||||
| } | |||||
| return anim->y; | return anim->y; | ||||
| } | } | ||||