FFmpeg解析视频文件头部信息

上一节讲了编译FFmpeg,并导入xcode进行断点调试,将源码正确导入了xcode,这节开始我们将陆续对FFmpeg进行二次开发,通过提供的API来获取我们想好的信息或者想做的事情。本节将讲一下如何解析本地视频文件的头部信息。

代码中的注释请详细看:

//
//  header_achieve.c
//  XCFFmpegDemo
//
//  Created by eggsy on 2018/7/23.
//  Copyright © 2018年 eggsy. All rights reserved.
//

#include "header_achieve.h"
#include "libavformat/avformat.h"
#include "libavutil/dict.h"

void achieve_header(char *dst_file_path) {
  FILE *dst_file = fopen(dst_file_path, "r");
  if (dst_file != NULL) {
    struct AVFormatContext *ctx = avformat_alloc_context();
    av_register_all();
    // 打开输入流,并且解析头部,解码器并不会打开,必须使用avformat_close_input()关闭
    // 返回结果0代表成功, 负数AVERROR表示失败.
    if (avformat_open_input(&ctx, dst_file_path, NULL, NULL) != 0) {
      printf("open dst file error!!!");
    } else {
      /**
       * 元数据
       */
      AVDictionary *metadata = ctx->metadata;
      int count = av_dict_count(metadata);
      AVDictionaryEntry *prev = NULL;
      if (count) {
        printf("achieve meta datas :\n");
        for (int i = 0; i < count; i++) {
          prev = av_dict_get(metadata, "", prev, AV_DICT_IGNORE_SUFFIX);
          if (prev) {
            printf("%s = %s \n", prev->key, prev->value);
          }
        }
      }
      printf("\nmetadata count size %d \n", count);

      /**
       * 视频时长
       */
      int64_t duration = ctx->duration;
      if (duration != AV_NOPTS_VALUE) {
        double_t duration_seconds = (double_t)duration / AV_TIME_BASE;
        printf("video duration %.2f seconds \n", duration_seconds);
      }

      /**
       * 码率,如果为0,则不存在码率;如果知道文件大小和时长的情况下无需直接手动设置,ffmpeg会自动计算
       */
      int64_t bit_rate = ctx->bit_rate;
      if (bit_rate > 0) {
        printf("video bitrate %d\n", bit_rate);
      } else {
        printf("video bitrate N/A\n");
      }

      /**
       * 第一帧起始时间,无需手动设置,由AVStream中推导出来,单位是xxx/AV_TIME_BASE(秒)
       */
      int64_t start_time = ctx->start_time;
      if (start_time != AV_NOPTS_VALUE) {
        double_t start_time_seconds = (double_t)start_time / AV_TIME_BASE;
        printf("video start time %.5f\n", start_time_seconds);
      }

      /**
       * 流信息
       */
      printf("\n-----STREAM_INFOS-----\n");
      AVStream **streams = ctx->streams;
      int stream_counts = ctx->nb_streams;
      if (stream_counts > 0) {
        for (int index = 0; index < stream_counts; index++) {
          printf("\n---STREAM---\n");
          AVStream *stream = streams[index];
          int stream_index = stream->index;
          printf("stream index %d\n", stream_index);
          // 后续讲到视频播放的时候会再次重点解析一下这个区域的信息
          printf("stream info parse...");
        }
      }

      printf("\n\nstream count %d\n", stream_counts);
    }

    avformat_close_input(&ctx);
  } else {
    printf("open dst file error!!!");
  }
}

void print_header(char *dst_file_path) {
  FILE *dst_file = fopen(dst_file_path, "r");
  if (dst_file != NULL) {
    struct AVFormatContext *ctx = avformat_alloc_context();
    av_register_all();
    // 打开输入流,并且解析头部,解码器并不会打开,必须使用avformat_close_input()关闭
    // 返回结果0代表成功, 负数AVERROR表示失败.
    if (avformat_open_input(&ctx, dst_file_path, NULL, NULL) != 0) {
      printf("open dst file error!!!");
    } else {
      // 读取avformat_open_input后,头部信息就存在于ctx中,这里进行一个简单的打印,当然你也可以自己独子获取其中的某些变量
      av_dump_format(ctx, 0, dst_file_path, 0);
    }
    avformat_close_input(&ctx);
  } else {
    printf("open dst file error!!!");
  }
    
}

由于流信息内容较多,字段没有一一解析出来展示,这里只是告诉大家如何解析,在有需要的时候,可以方便使用该方法解析出来,我们的目的就达到了,下一节会讲一下如何调用API播放一个mp4视频。

你可能感兴趣的:(FFmpeg解析视频文件头部信息)