版权声明: https://blog.csdn.net/u013470102/article/details/89473570
一app开发,火急火燎的拿来一个视频,说录制的视频播放角度都不正常。拿过来一看,确实,角度是歪的,用系统的mediaplayer一试,是正常的。把视频放到ffmpeg中,可以看到视频metadata下视频旋转角度是90度。
ijk中有提供视频角度旋转的接口:
//开启自动旋转,这里旋转的是视频
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
//关闭自动旋转
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
那么我们看下这个接口做了什么呢?
这个在recreate_format_l/ffpipenode_android_mediacodec_vdec.c函数中
//获取视频旋转角度
rotate_degrees = ffp_get_video_rotate_degrees(ffp);
//如果上层开启旋转,也就是上面设置的2个接口,同时视频角度不为0
if (ffp->mediacodec_auto_rotate &&
rotate_degrees != 0 &&
SDL_Android_GetApiLevel() >= IJK_API_21_LOLLIPOP) {
ALOGI("amc: rotate in decoder: %d\n", rotate_degrees);
opaque->frame_rotate_degrees = rotate_degrees;
//把获取的视频角度设置给mediaformat
SDL_AMediaFormat_setInt32(opaque->input_aformat, "rotation-degrees", rotate_degrees);
//通知上层,视频角度改变了
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_ROTATION_CHANGED, 0);
} else {
ALOGI("amc: rotate notify: %d\n", rotate_degrees);
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_ROTATION_CHANGED, rotate_degrees);
}
看一下获取视频角度ffp_get_video_rotate_degrees/ff_ffplay.c函数:
//获取视频角度
int ffp_get_video_rotate_degrees(FFPlayer *ffp)
{
VideoState *is = ffp->is;
if (!is)
return 0;
//获取的角度%360度,不足的还是原来的值
int theta = abs((int)((int64_t)round(fabs(get_rotation(is->video_st))) % 360));
switch (theta) {
//如果角度是0 90 180 270度,则不处理,直接跳出来
case 0:
case 90:
case 180:
case 270:
break;
//如果角度是360度,则置0
case 360:
theta = 0;
break;
default://或者置0
ALOGW("Unknown rotate degress: %d\n", theta);
theta = 0;
break;
}
return theta;
}
继续跟踪函数get_rotation/ff_cmdutils.c函数
double get_rotation(AVStream *st)
{
//从metadata的rotate获取视频旋转角度
AVDictionaryEntry *rotate_tag = av_dict_get(st->metadata, "rotate", NULL, 0);
uint8_t* displaymatrix = av_stream_get_side_data(st,
AV_PKT_DATA_DISPLAYMATRIX, NULL);
double theta = 0;
if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) {
char *tail;
theta = av_strtod(rotate_tag->value, &tail);
if (*tail)
theta = 0;
}
if (displaymatrix && !theta)
theta = -av_display_rotation_get((int32_t*) displaymatrix);
theta -= 360*floor(theta/360 + 0.9/360);
if (fabs(theta - 90*round(theta/90)) > 2)
av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.\n"
"If you want to help, upload a sample "
"of this file to ftp://upload.ffmpeg.org/incoming/ "
"and contact the ffmpeg-devel mailing list. ([email protected])");
return theta;
}
那么从上面我们就可以知道,视频的整个旋转流程就是从metadata中获取rotate,也就是拿到视频的角度,然后在创建mediaformat的时候,设置给mediaformat。这样就改变了视频的旋转角度。那么应用上层做了针对重力的视频旋转,这个有没有问题呢?目前没收到反馈。