【问题标题】:How to disable libav autorotate display matrix如何禁用 libav 自动旋转显示矩阵
【发布时间】:2017-12-07 17:17:05
【问题描述】:

我有一个从我的手机以纵向模式拍摄的视频。以下是有关视频的转储信息:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.MOV':
Metadata:
major_brand     : qt  
minor_version   : 0
compatible_brands: qt  
creation_time   : 2017-05-04 02:21:37
Duration: 00:00:06.91, start: 0.000023, bitrate: 4700 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 90 kb/s (default)
Metadata:
  creation_time   : 2017-05-04 02:21:37
  handler_name    : Core Media Data Handler
Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720, 4602 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
Metadata:
  rotate          : 90
  creation_time   : 2017-05-04 02:21:37
  handler_name    : Core Media Data Handler
  encoder         : H.264
Side data:
  displaymatrix: rotation of -90.00 degrees
  5.78 A-V: -0.028 fd=   1 aq=   14KB vq=  351KB sq=    0B f=0/0   

我正在使用 libav api 来解码/编码我的视频。编码后,我得到视频的旋转版本 -90 度。

如何停止解码器以防止自动旋转?

【问题讨论】:

  • 查看cli工具的-noautorotate选项相关的源码。
  • @LordNeckbeard,我这样做了,但在 libav api 中禁用 autorotae 仍然存在问题。能否提供详细信息?

标签: ffmpeg libavcodec libav


【解决方案1】:

经过长时间处理显示矩阵端数据引起的问题,我遇到了以下解决方案:

将元数据和辅助数据与视频流一起复制。 这段代码可以解决问题

AVStream *in_stream; //input stream
AVStream *out_stream; //output stream
....        
if(in_stream->side_data!=NULL){

  av_log(NULL, AV_LOG_ERROR, "side data size: %d , size: %d\n", in_stream->side_data->size, sizeof(uint8_t*));

        if(av_stream_get_side_data(in_stream , AV_PKT_DATA_DISPLAYMATRIX, sd_size)!=NULL){

            uint8_t* resp=(uint8_t*) av_mallocz(in_stream->side_data->size+
                                                AV_INPUT_BUFFER_MIN_SIZE);


            resp  = av_stream_get_side_data(in_stream , AV_PKT_DATA_DISPLAYMATRIX, sd_size);

              av_log(NULL, AV_LOG_DEBUG,"side data detected, size :%d vs %d, "
                                        "nb_side_data %d, sizeof data %d,"
                                        " sizeof resp %d\n",
                     *sd_size, in_stream->side_data->size ,in_stream->nb_side_data,
                     in_stream->side_data->size*sizeof(uint8_t*),sizeof(resp));
              in_stream->side_data->data = (uint8_t*) av_mallocz(
                          in_stream->side_data->size*sizeof(uint8_t*)
                          );
              hasRotation = true; /* it will be used for 
              something like ffmpeg does with noautorotate flag */
              av_stream_add_side_data(out_stream, AV_PKT_DATA_DISPLAYMATRIX, resp, *sd_size);

        }
    }

生成的视频会有一个显示矩阵,一些播放器会正确显示它们。

使用简单的过滤器 如上所示,可以检测到视频是否旋转。在我的情况下,旋转是-90,所以我使用 transpose=clock 过滤器来启动我的过滤器图。考虑 ffmpeg 3.4.1 中的转码示例。我将代码更改如下以禁用自动旋转 -90 度。

static int init_filters(void)
{
    const char *filter_spec;
    unsigned int i;
    int ret;
    filter_ctx = (FilteringContext*) av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));
if (!filter_ctx)
    return AVERROR(ENOMEM);
     for (i = 0; i < ifmt_ctx->nb_streams; i++) {
       filter_ctx[i].buffersrc_ctx  = NULL;
       filter_ctx[i].buffersink_ctx = NULL;
       filter_ctx[i].filter_graph   = NULL;
       if (!(ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
            || ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO))
        continue;
        if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        filter_spec = isRotated ?"transpose=clock":"null"; /* passthrough (dummy) filter for video */
    else
        filter_spec = "anull"; /* passthrough (dummy) filter for audio */
    ret = init_filter(&filter_ctx[i], stream_ctx[i].dec_ctx,
            stream_ctx[i].enc_ctx, filter_spec);
    if (ret)
        return ret;
}
return 0;
}

请注意,编码器尺寸也应该交换。意思是:

enc_ctx->width = dec_ctx->height; 
enc_ctx->height = enc_ctx->width;

我希望它可以帮助其他人。

【讨论】:

    猜你喜欢
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多