前段时间把环境整了下,闲时学习下ffmpeg.
最近在看雷神的创作,边看,边学,感谢雷神!
头文件:
//
// ffmpeg_read_av_info.hpp
// ffmpegDemo
//
// Created by fengsh on 2018/4/15.
// Copyright © 2018年 fengsh998@163.com. All rights reserved.
//
/**
音视频文件信息读取
*/
#ifndef ffmpeg_read_av_info_hpp
#define ffmpeg_read_av_info_hpp
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/pixdesc.h"
#include "libavutil/pixfmt.h"
void read_av_info(const char * av_pathfile);
#endif /* ffmpeg_read_av_info_hpp */
.c文件
//
// ffmpeg_read_av_info.c
// ffmpegDemo
//
// Created by fengsh on 2018/4/15.
// QQ : 19985430
// Copyright © 2018年 fengsh998@163.com. All rights reserved.
//
/**
音视频文件信息读取 (ffmpeg version 3.4.2)
control+command + 空格 打特殊符号
*/
/*
FFmpeg解码流程图(参考雷神的备忘)
av_register_all()
↓
avformat_open_input()
↓
avformat_find_stream_info()
↓
avcodec_find_decoder()
↓
avcodec_open2()
|-------------------------------------------←--------
↓ |
av_read_frame() |
↓ |
get packet?----------YES-------------- |
| ↓ |
NO AVPacket ↑
| ↓ |
| avcodec_decode_video2() |
↓ ↓ |
close AVFrame |
↓ |
show on screen.. |
↓ |
|__________________|
*/
#include "ffmpeg_read_av_info.h"
char* BytesToSize( double Bytes )
{
float tb = 1099511627776;
float gb = 1073741824;
float mb = 1048576;
float kb = 1024;
char returnSize[256];
if( Bytes >= tb )
sprintf(returnSize, "%.2f TB", (float)Bytes/tb);
else if( Bytes >= gb && Bytes < tb )
sprintf(returnSize, "%.2f GB", (float)Bytes/gb);
else if( Bytes >= mb && Bytes < gb )
sprintf(returnSize, "%.2f MB", (float)Bytes/mb);
else if( Bytes >= kb && Bytes < mb )
sprintf(returnSize, "%.2f KB", (float)Bytes/kb);
else if ( Bytes < kb)
sprintf(returnSize, "%.2f Bytes", Bytes);
else
sprintf(returnSize, "%.2f Bytes", Bytes);
static char ret[256];
strcpy(ret, returnSize);
return ret;
}
void read_av_info(const char * av_pathfile)
{
AVFormatContext *pfmtCxt = NULL;
int audioStreamIdx = -1;
int videoStreamIdx = -1;
//初始化 libavformat和注册所有的muxers、demuxers和protocols
av_register_all();
//以输入方式打开一个媒体文件,也即源文件
int ok = avformat_open_input(&pfmtCxt, av_pathfile, NULL, NULL);
if (ok != 0) {
printf("Could not open file.");
}
//通过读取媒体文件的中的包来获取媒体文件中的流信息,对于没有头信息的文件如(mpeg)是非常有用的
//也就是把媒体文件中的音视频流等信息读出来,保存在容器中,以便解码时使用
ok = avformat_find_stream_info(pfmtCxt, NULL);
if (ok != 0) {
printf("find stream info error.");
}
for (int i = 0; i < pfmtCxt->nb_streams; i++) {
if (pfmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIdx = i;
} else if (pfmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStreamIdx = i;
}
}
AVStream *videostream = NULL;
AVStream *audiostream = NULL;
if (videoStreamIdx != -1) {
videostream = pfmtCxt->streams[videoStreamIdx];
}
if (audioStreamIdx != -1) {
audiostream = pfmtCxt->streams[audioStreamIdx];
}
printf("==============================av_dump_format==================================\n");
av_dump_format(pfmtCxt, 0, 0, 0);
/*******************************输出相关media文件信息*******************************/
printf("===========================================================================\n");
printf("文件名 : %s \n",pfmtCxt->url);
printf("输入格式 : %s \n全称 : %s \n",pfmtCxt->iformat->name,pfmtCxt->iformat->long_name);
int64_t tns, thh, tmm, tss;
tns = pfmtCxt->duration / 1000000;
thh = tns / 3600;
tmm = (tns % 3600) / 60;
tss = (tns % 60);
printf("总时长 : %f ms,fmt:%02lld:%02lld:%02lld \n总比特率 : %f kbs\n",(pfmtCxt->duration * 1.0 / AV_TIME_BASE) * 1000,thh,tmm,tss,pfmtCxt->bit_rate / 1000.0);//1000 bit/s = 1 kbit/s
double fsize = (pfmtCxt->duration * 1.0 / AV_TIME_BASE * pfmtCxt->bit_rate / 8.0);
printf("文件大小 : %s\n",BytesToSize(fsize));
printf("协议白名单 : %s \n协义黑名单 : %s\n",pfmtCxt->protocol_whitelist,pfmtCxt->protocol_blacklist);
printf("数据包的最大数量 : %d\n",pfmtCxt->max_ts_probe);
printf("最大缓冲时间 : %lld\n",pfmtCxt->max_interleave_delta);
printf("缓冲帧的最大缓冲 : %u Bytes\n",pfmtCxt->max_picture_buffer);
printf("metadata:\n");
AVDictionary *metadata = pfmtCxt->metadata;
if (metadata) {
AVDictionaryEntry *entry = NULL;
while ((entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
printf("\t%s : %s\n",entry->key,entry->value);
}
}
if (videostream) {
printf("视频流信息(%s):\n",av_get_media_type_string(videostream->codecpar->codec_type));
printf("\tStream #%d\n",videoStreamIdx);
printf("\t总帧数 : %lld\n",videostream->nb_frames);
const char *avcodocname = avcodec_get_name(videostream->codecpar->codec_id);
const char *profilestring = avcodec_profile_name(videostream->codecpar->codec_id,videostream->codecpar->profile);
char * codec_fourcc = av_fourcc2str(videostream->codecpar->codec_tag);
printf("\t编码方式 : %s\n\tCodec Profile : %s\n\tCodec FourCC : %s\n",avcodocname,profilestring,codec_fourcc);
///如果是C++引用(AVPixelFormat)注意下强转类型
const char *pix_fmt_name = videostream->codecpar->format == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(videostream->codecpar->format);
printf("\t显示编码格式(color space) : %s \n",pix_fmt_name);
printf("\t宽 : %d pixels,高 : %d pixels \n",videostream->codecpar->width,videostream->codecpar->height);
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
videostream->codecpar->width * (int64_t)videostream->sample_aspect_ratio.num,
videostream->codecpar->height * (int64_t)videostream->sample_aspect_ratio.den,
1024 * 1024);
printf("\tsimple_aspect_ratio(SAR) : %d : %d\n\tdisplay_aspect_ratio(DAR) : %d : %d \n",videostream->sample_aspect_ratio.num,
videostream->sample_aspect_ratio.den,display_aspect_ratio.num,display_aspect_ratio.den);
printf("\t最低帧率 : %f fps\n\t平均帧率 : %f fps\n",av_q2d(videostream->r_frame_rate),av_q2d(videostream->avg_frame_rate));
printf("\t每个像素点的比特数 : %d bits\n",videostream->codecpar->bits_per_raw_sample);
printf("\t每个像素点编码比特数 : %d bits\n",videostream->codecpar->bits_per_coded_sample); //YUV三个分量每个分量是8,即24
printf("\t视频流比特率 : %f kbps\n",videostream->codecpar->bit_rate / 1000.0);
printf("\t基准时间 : %d / %d = %f \n",videostream->time_base.num,videostream->time_base.den,av_q2d(videostream->time_base));
printf("\t视频流时长 : %f ms\n",videostream->duration * av_q2d(videostream->time_base) * 1000);
printf("\t帧率(tbr) : %f\n",av_q2d(videostream->r_frame_rate));
printf("\t文件层的时间精度(tbn) : %f\n",1/av_q2d(videostream->time_base));
printf("\t视频层的时间精度(tbc) : %f\n",1/av_q2d(videostream->codec ->time_base));
double s = videostream->duration * av_q2d(videostream->time_base);
int64_t tbits = videostream->codecpar->bit_rate * s;
double stsize = tbits / 8;
printf("\t视频流大小(Bytes) : %s \n",BytesToSize(stsize));
printf("\tmetadata:\n");
AVDictionary *metadata = videostream->metadata;
if (metadata) {
AVDictionaryEntry *entry = NULL;
while ((entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX))) {
printf("\t\t%s : %s\n",entry->key,entry->value);
}
}
}
if (audiostream) {
printf("音频流信息(%s):\n",av_get_media_type_string(audiostream->codecpar->codec_type));
printf("\tStream #%d\n",audioStreamIdx);
printf("\t音频时长 : %f ms\n",audiostream->duration * av_q2d(audiostream->time_base) * 1000);
const char *avcodocname = avcodec_get_name(audiostream->codecpar->codec_id);
const char *profilestring = avcodec_profile_name(audiostream->codecpar->codec_id,audiostream->codecpar->profile);
char * codec_fourcc = av_fourcc2str(audiostream->codecpar->codec_tag);
printf("\t编码格式 %s (%s,%s)\n",avcodocname,profilestring,codec_fourcc);
printf("\t音频采样率 : %d Hz\n",audiostream->codecpar->sample_rate);
printf("\t音频声道数 : %d \n",audiostream->codecpar->channels);
printf("\t音频流比特率 : %f kbps\n",audiostream->codecpar->bit_rate / 1000.0);
double s = audiostream->duration * av_q2d(audiostream->time_base);
int64_t tbits = audiostream->codecpar->bit_rate * s;
double stsize = tbits / 8;
printf("\t音频流大小(Bytes) : %s\n",BytesToSize(stsize));
}
}
输出的结果 :
==============================av_dump_format==================================
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '(null)':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.41.100
comment : vid:74f08a0dec84478db32d577dc195f449
Duration: 00:02:58.64, start: 0.000000, bitrate: 518 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 854x480 [SAR 1280:1281 DAR 16:9], 450 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 63 kb/s (default)
Metadata:
handler_name : SoundHandler
===========================================================================
文件名 : /Users/fengsh/Documents/ffmpeg/test.mp4
输入格式 : mov,mp4,m4a,3gp,3g2,mj2
全称 : QuickTime / MOV
总时长 : 178641.000000 ms,fmt:00:02:58
总比特率 : 518.820000 kbs
文件大小 : 11.05 MB
协议白名单 : file,crypto
协义黑名单 : (null)
数据包的最大数量 : 50
最大缓冲时间 : 10000000
缓冲帧的最大缓冲 : 3041280 Bytes
metadata:
major_brand : isom
minor_version : 512
compatible_brands : isomiso2avc1mp41
encoder : Lavf57.41.100
comment : vid:74f08a0dec84478db32d577dc195f449
视频流信息(video):
Stream #0
总帧数 : 4460
编码方式 : h264
Codec Profile : High
Codec FourCC : avc1
显示编码格式(color space) : yuv420p
宽 : 854 pixels,高 : 480 pixels
simple_aspect_ratio(SAR) : 1280 : 1281
display_aspect_ratio(DAR) : 16 : 9
最低帧率 : 25.000000 fps
平均帧率 : 25.000000 fps
每个像素点的比特数 : 8 bits
每个像素点编码比特数 : 24 bits
视频流比特率 : 450.393000 kbps
基准时间 : 1 / 12800 = 0.000078
视频流时长 : 178400.000000 ms
帧率(tbr) : 25.000000
文件层的时间精度(tbn) : 12800.000000
视频层的时间精度(tbc) : 50.000000
视频流大小(Bytes) : 9.58 MB
metadata:
language : und
handler_name : VideoHandler
音频流信息(audio):
Stream #1
音频时长 : 178526.009070 ms
编码格式 aac (HE-AAC,mp4a)
音频采样率 : 44100 Hz
音频声道数 : 2
音频流比特率 : 63.971000 kbps
音频流大小(Bytes) : 1.36 MB
估计还有其它格式的文件还没有考虑到,后面熟释了,搞个mac版本的工具玩玩。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/36115.html