網站首頁 編程語言 正文
一、通過此文可以得到什么
通過此練習:
1、知道了如何計算一個音頻和視頻的播放時間;
2、知道了音視頻解碼的思路的大體流程,之后無非就是在這個流程上進行擴充細節;
3、知道了如何通過C語言或者C++編程語言結合ffmpeg拿到一些音視頻的關鍵信息,例如:幀率等;
二、實現思路
三、實現效果
zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$ make make all make[1]: 進入目錄“/data/project/VSCProject/ffmpegStudy/src” Compiling main.cpp to main.o .. cp hello /data/project/VSCProject/ffmpegStudy/src/../ # make 【hello】 finish !!! make[1]: 離開目錄“/data/project/VSCProject/ffmpegStudy/src” zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$ zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$ ./hello Hello World ! decode video fileName=/home/zhenghui/視頻/1080P.mp4 [NULL @ 0x5654cc332d80] Opening '/home/zhenghui/視頻/1080P.mp4' for reading [file @ 0x5654cc333380] Setting default whitelist 'file,crypto,data' [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Format mov,mp4,m4a,3gp,3g2,mj2 probed with size=2048 and score=100 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] ISO: File Type Major Brand: isom [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Unknown dref type 0x206c7275 size 12 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Processing st: 0, edit list 0 - media time: 1072, duration: 3621888 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Offset DTS by 1072 to make first pts zero. [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Setting codecpar->delay to 2 for stream st: 0 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Unknown dref type 0x206c7275 size 12 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Processing st: 1, edit list 0 - media time: 0, duration: 9990149 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 29.916667 0.006250 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 30.000000 0.000066 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 60.000000 0.000265 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 120.000000 0.001061 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 240.000000 0.004244 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 29.970030 0.000868 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] rfps: 59.940060 0.003473 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] Before avformat_find_stream_info() pos: 87425182 bytes read:315205 seeks:1 nb_streams:2 [h264 @ 0x5654cc3340c0] nal_unit_type: 7(SPS), nal_ref_idc: 3 [h264 @ 0x5654cc3340c0] nal_unit_type: 8(PPS), nal_ref_idc: 3 [h264 @ 0x5654cc3340c0] nal_unit_type: 7(SPS), nal_ref_idc: 3 [h264 @ 0x5654cc3340c0] nal_unit_type: 8(PPS), nal_ref_idc: 3 [h264 @ 0x5654cc3340c0] nal_unit_type: 6(SEI), nal_ref_idc: 0 [h264 @ 0x5654cc3340c0] nal_unit_type: 5(IDR), nal_ref_idc: 3 [h264 @ 0x5654cc3340c0] Format yuv420p chosen by get_format(). [h264 @ 0x5654cc3340c0] Reinit context to 1920x1088, pix_fmt: yuv420p [h264 @ 0x5654cc3340c0] no picture [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] All info found [mov,mp4,m4a,3gp,3g2,mj2 @ 0x5654cc332d80] After avformat_find_stream_info() pos: 53231 bytes read:393067 seeks:2 frames:4 video_index=0 audio_index=1 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/zhenghui/視頻/1080P.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.29.100 description : Packed by Bilibili XCoder v2.0.2 Duration: 00:03:46.53, start: 0.000000, bitrate: 3087 kb/s Stream #0:0[0x1](und), 3, 1/16000: Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(progressive, left), 1920x1080 (1920x1088) [SAR 1:1 DAR 16:9], 0/1, 2951 kb/s, 30 fps, 30 tbr, 16k tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1[0x2](und), 1, 1/44100: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0] media name =/home/zhenghui/視頻/1080P.mp4 stream number: 2 media average ratio: 3015 kbps media total time: 0:3:46 ######## Video info: ######## stream index : 0 fps:29.999914 fps video codec : H264 video_time : 00:03:46 ######## Audio info: ######## stream index : 1 stream sample_rate : 44100 Hz stream format : AV_SAMPLE_FMT_FLTP channels number:2 audio codec:AAC audio_time : 00:03:46 [AVIOContext @ 0x5654cc33b7c0] Statistics: 393067 bytes read, 2 seeks zhenghui@zh-pc:/data/project/VSCProject/ffmpegStudy$
四、實現源代碼?
#include <iostream>
#include <stdio.h>
#ifdef __cplusplus //表示是一個c++程序
extern "C"{
#endif
#include <libavdevice/avdevice.h>
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
#include <libavutil/log.h>
#include <libswscale/swscale.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#ifdef __cplusplus
}
#endif
//g++ -I ../include/ hello_world.cpp -o hello_world -L../lib/ -lavcodec -lavdevice -lavfilter -lavformat -lavutil
void decode()
{
char *fileName = "/home/zhenghui/視頻/1080P.mp4";
printf("decode video fileName=%s \n",fileName);
int ret = 0;
// 1、分配解復用器上下文
AVFormatContext *ctx = NULL;
ctx = avformat_alloc_context();
// 2、根據url打開本地文件或網絡流
ret = avformat_open_input(&ctx,fileName,NULL,NULL);
if(ret < 0)
{
printf("打開%s失敗 ! \n",fileName);
return;
}
// 3、讀取媒體的部分數據包,獲取碼流信息
ret = avformat_find_stream_info(ctx,NULL);
if(ret < 0){
printf("獲取碼流信息失敗 !\n");
return;
}
// 3、獲取音頻流和視頻流的索引
int video_index = -1;
int audio_index = -1;
video_index = av_find_best_stream(ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
printf("video_index=%d \n",video_index);
audio_index = av_find_best_stream(ctx,AVMEDIA_TYPE_AUDIO,-1,-1,NULL,0);
printf("audio_index=%d \n",audio_index);
// 打印流信息
av_dump_format(ctx,0,fileName,0);
//打印媒體文件url
printf("media name =%s \n",ctx->url);
//打印流數量
printf("stream number: %d \n",ctx->nb_streams);
//打印碼率
printf("media average ratio: %lld kbps\n",(int64_t)(ctx->bit_rate/1024));
//打印時長
int total_seconds,hour,minute,second;
//ctx->duration的單位是微妙,先轉換成秒,再進行轉換成其他的時間單位就比較簡單了
total_seconds = (ctx->duration) / AV_TIME_BASE;
hour = total_seconds / 3600;
minute = (total_seconds % 3600) /60;
second = (total_seconds % 60);
// 文件總時長
printf("media total time: %d:%d:%d \n",hour,minute,second);
//老版本查找流索引
for(int i = 0;i < ctx->nb_streams;i++){
AVStream *av_stream = ctx->streams[i];
//判斷流是什么類型
//視頻流
if( AVMEDIA_TYPE_VIDEO == av_stream->codecpar->codec_type)
{
printf("######## Video info: ######## \n");
// 流索引
printf("stream index : %d \n",av_stream->index);
//幀率
printf("fps:%lf fps\n",av_q2d(av_stream->avg_frame_rate));
if(AV_CODEC_ID_MPEG4 == av_stream->codecpar->codec_id)
{
printf("video codec : MPEG4 \n");
}
else if(AV_CODEC_ID_H264 == av_stream->codecpar->codec_id)
{
printf("video codec : H264 \n");
}else
{
printf("video codec other value=%d \n", av_stream->codecpar->codec_id);
}
//獲取視頻總時長
if(AV_NOPTS_VALUE != av_stream->duration)
{
int video_time =av_stream->duration * av_q2d(av_stream->time_base);
printf("video_time : %02d:%02d:%02d\n" ,
(video_time / 3600),
(video_time % 3600) / 60,
(video_time % 60)
);
}
else{
printf("audio duration unknown ! \n");
}
}
//音頻流
else if(AVMEDIA_TYPE_AUDIO == av_stream->codecpar->codec_type)
{
printf("######## Audio info: ######## \n");
// 流索引
printf("stream index : %d \n",av_stream->index);
// 音頻編解碼器的采樣率 單位Hz
printf("stream sample_rate : %d Hz \n",av_stream->codecpar->sample_rate);
//音頻采樣格式
if(AV_SAMPLE_FMT_FLTP == av_stream->codecpar->format)
{
printf("stream format : AV_SAMPLE_FMT_FLTP \n");
}
else if(AV_SAMPLE_FMT_S16P == av_stream->codecpar->format)
{
printf("stream format : AV_SAMPLE_FMT_S16P \n");
}else{
printf("stream format : other; value=%d \n",av_stream->codecpar->format);
}
// 音頻信道數目
printf("channels number:%d \n",av_stream->codecpar->channels);
//音頻壓縮編碼格式
if(AV_CODEC_ID_AAC == av_stream->codecpar->codec_id)
{
printf("audio codec:AAC \n");
}else if(AV_CODEC_ID_MP3 == av_stream->codecpar->codec_id)
{
printf("audio codec:MP3 \n");
}else{
printf("audio codec : other; value=%d \n",av_stream->codecpar->codec_id);
}
//獲取視頻總時長
if(AV_NOPTS_VALUE != av_stream->duration)
{
int audio_time =av_stream->duration * av_q2d(av_stream->time_base);
printf("audio_time : %02d:%02d:%02d\n" ,
(audio_time / 3600),
(audio_time % 3600) / 60,
(audio_time % 60)
);
}
else{
printf("audio duration unknown ! \n");
}
audio_index = i;
}
}
if(ctx)
avformat_close_input(&ctx);
}
int main() {
// 設置控制臺輸出級別
av_log_set_level(AV_LOG_DEBUG);
// // 打印輸出字符串Hello World !
av_log(NULL, AV_LOG_DEBUG, "%s", "Hello World !\n");
decode();
return 0;
}
原文鏈接:https://blog.csdn.net/qq_17623363/article/details/122151819
相關推薦
- 2022-07-09 Python小技巧練習分享_python
- 2023-04-26 C語言實現數組元素排序方法詳解_C 語言
- 2022-06-19 詳解.Net中字符串不變性與相等判斷的特殊場景_實用技巧
- 2022-05-10 antd的timePicker.RangePicker設置結束時間不可早于開始時間
- 2022-06-13 云計算openstack框架分類及發展階段概述_OpenStack
- 2022-02-25 DevTools failed to load SourceMap 警告處理方法
- 2022-11-27 Oracle?中檢查臨時表空間的方法_oracle
- 2022-05-11 Excel表中數據轉為sql
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支