Fix #107493: Auto rotate videos fix #115661

Open
ErikHK wants to merge 7 commits from ErikHK/blender:auto_rotate_video into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 52 additions and 0 deletions

View File

@ -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. */

View File

@ -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);
ErikHK marked this conversation as resolved Outdated

const double theta = av_display_rotation_get((int32_t *)displaymatrix);

`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;

View File

@ -108,3 +108,32 @@ void IMB_flipx(ImBuf *ibuf)
}
}
}
void IMB_rotate90(ImBuf *ibuf)
{
if (ibuf == nullptr)
return;
ErikHK marked this conversation as resolved
Review

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--) {
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--) {`
/* 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;
ErikHK marked this conversation as resolved Outdated

nullptr instead of 0.

`nullptr` instead of `0`.
uint *ibufrect = (uint *)ibuf->byte_buffer.data;
int skip = ibuf->x;
uint *rect;
for (int y = ibuf->x - 1; y >= 0; y--) {

You can duplicate just the data, and use that as a const-source , and write the rotated result directly to the ibuf->byte_buffer. This way you wouldn't need the extra memcpy after the loop.

You can duplicate just the data, and use that as a const-source , and write the rotated result directly to the `ibuf->byte_buffer`. This way you wouldn't need the extra `memcpy` after the loop.

Thanks for the tip! I think I solved it in the way you suggested, but since I'm not great at memory handling and stuff in C it would be nice if you could take a look at it :)

Thanks for the tip! I think I solved it in the way you suggested, but since I'm not great at memory handling and stuff in C it would be nice if you could take a look at it :)
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);
}