Fix #107493: Auto rotate videos fix #115661
|
@ -749,6 +749,7 @@ struct ImBuf *IMB_double_y(struct ImBuf *ibuf1);
|
|||
*/
|
||||
void IMB_flipx(struct ImBuf *ibuf);
|
||||
void IMB_flipy(struct ImBuf *ibuf);
|
||||
void IMB_rotate90(struct ImBuf *ibuf);
|
||||
|
||||
/* Pre-multiply alpha. */
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ extern "C" {
|
|||
# include <libavutil/rational.h>
|
||||
# include <libswscale/swscale.h>
|
||||
|
||||
# include <libavutil/display.h>
|
||||
|
||||
# include "ffmpeg_compat.h"
|
||||
}
|
||||
|
||||
|
@ -875,6 +877,25 @@ static void ffmpeg_postprocess(anim *anim, AVFrame *input, ImBuf *ibuf)
|
|||
if (filter_y) {
|
||||
IMB_filtery(ibuf);
|
||||
}
|
||||
|
||||
/* auto rotate video */
|
||||
/* get display matrix rotation to see if a rotation is in order: */
|
||||
uint8_t *displaymatrix = av_stream_get_side_data(
|
||||
anim->pFormatCtx->streams[anim->videoStream], AV_PKT_DATA_DISPLAYMATRIX, NULL);
|
||||
|
||||
if (displaymatrix == nullptr)
|
||||
return;
|
||||
|
||||
const double theta = av_display_rotation_get((int32_t *)displaymatrix);
|
||||
|
||||
/* perform rotation */
|
||||
if (theta == -90) {
|
||||
IMB_rotate90(ibuf);
|
||||
}
|
||||
else if (theta == 180 || theta == -180) {
|
||||
IMB_flipx(ibuf);
|
||||
IMB_flipy(ibuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void final_frame_log(anim *anim,
|
||||
|
@ -1386,6 +1407,7 @@ static ImBuf *ffmpeg_fetchibuf(anim *anim, int position, IMB_Timecode_Type tc)
|
|||
ffmpeg_decode_video_frame_scan(anim, pts_to_search);
|
||||
|
||||
/* Update resolution as it can change per-frame with WebM. See #100741 & #100081. */
|
||||
|
||||
anim->x = anim->pCodecCtx->width;
|
||||
anim->y = anim->pCodecCtx->height;
|
||||
|
||||
|
|
|
@ -108,3 +108,32 @@ void IMB_flipx(ImBuf *ibuf)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_rotate90(ImBuf *ibuf)
|
||||
{
|
||||
if (ibuf == nullptr)
|
||||
return;
|
||||
ErikHK marked this conversation as resolved
|
||||
|
||||
/* create a temporary copy of the image */
|
||||
uint8_t *imgdata = (uint8_t *)malloc(ibuf->x * ibuf->y * sizeof(uint));
|
||||
memcpy(imgdata, ibuf->byte_buffer.data, ibuf->x * ibuf->y * sizeof(uint));
|
||||
|
||||
uint *imgdatarect = (uint *)imgdata;
|
||||
uint *ibufrect = (uint *)ibuf->byte_buffer.data;
|
||||
int skip = ibuf->x;
|
||||
|
||||
uint *rect;
|
||||
for (int y = ibuf->x - 1; y >= 0; y--) {
|
||||
rect = imgdatarect + y;
|
||||
for (int x = ibuf->y; x > 0; x--) {
|
||||
*ibufrect++ = *rect;
|
||||
rect += skip;
|
||||
}
|
||||
}
|
||||
|
||||
/* swap width and height of ibuf */
|
||||
SWAP(int, ibuf->x, ibuf->y);
|
||||
|
||||
/* free temporary copy of image */
|
||||
free(imgdata);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Reduce the scope of variables. So instead of defining them in the beginning of the function define close to where you use htem. Examples:
ImBuf *tbuf = IMB_allocImBuf(ibuf->y, ibuf->x, 32, IB_rect);
for (int y = tbuf->y - 1; y >= 0; y--) {