FFmpeg简单学习:解封装基本流程

解封装流程

1.分配解复用器上下文avformat_alloc_context

2.根据url打开本地文件或网络流avformat_open_input

3.读取媒体的部分数据包以获取码流信息avformat_find_stream_info

4.读取码流信息:循环处理

  4.1 从文件中读取数据包av_read_frame

  4.2 定位文件avformat_seek_file或av_seek_frame

5.关闭解复用器avformat_close_input

代码基本流程如下:

  1 #include <stdio.h>
  2 #include ”libavformat/avformat.h”
  3 
  4 int main(int argc, char **argv)
  5 {
  6 
  7 // 1. 打开文件
  8     const char *ifilename = "1234.flv";
  9     printf("in_filename = %s\n", ifilename);
 10     // AVFormatContext是描述一个媒体文件或媒体流的构成和基本信息的结构体
 11     AVFormatContext *ifmt_ctx = NULL;           // 输入文件的demux
 12     // 打开文件,主要是探测协议类型,如果是网络文件则创建网络链接
 13     int ret = avformat_open_input(&ifmt_ctx, ifilename, NULL, NULL);
 14     if (ret < 0) {
 15         char buf[1024] = {0};
 16         av_strerror(ret, buf, sizeof (buf) - 1);
 17         printf("open %s failed: %s\n", ifilename, buf);
 18         return -1;
 19     }
 20 
 21 // 2. 读取码流信息
 22     ret = avformat_find_stream_info(ifmt_ctx, NULL);
 23     if (ret < 0)  //如果打开媒体文件失败,打印失败原因
 24     {
 25         char buf[1024] = { 0 };
 26         av_strerror(ret, buf, sizeof(buf) - 1);
 27         printf("avformat_find_stream_info %s failed:%s\n", ifilename, buf);
 28         avformat_close_input(&ifmt_ctx);
 29         return -1;
 30     }
 31 
 32 
 33 // 3.打印总体信息
 34     printf_s("\n==== av_dump_format in_filename:%s ===\n", ifilename);
 35     av_dump_format(ifmt_ctx, 0, ifilename, 0);
 36     printf_s("\n==== av_dump_format finish =======\n\n");
 37     printf("media name:%s\n", ifmt_ctx->url);
 38     printf("stream number:%d\n", ifmt_ctx->nb_streams); //  nb_streams媒体流数量
 39     printf("media average ratio:%lldkbps\n",(int64_t)(ifmt_ctx->bit_rate/1024)); //  媒体文件的码率,单位为bps
 40     // duration: 媒体文件时长,单位微妙
 41     int total_seconds = (ifmt_ctx->duration) / AV_TIME_BASE;  // 1000us = 1ms, 1000ms = 1秒
 42     printf("audio duration: %02d:%02d:%02d\n",
 43            total_seconds / 3600, (total_seconds % 3600) / 60, (total_seconds % 60));
 44     printf("\n");
 45 
 46 // 4.读取码流信息
 47     // 音频
 48     int audioindex = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
 49     if (audioindex < 0) {
 50         printf("av_find_best_stream %s eror.", av_get_media_type_string(AVMEDIA_TYPE_AUDIO));
 51         return -1;
 52     }
 53     AVStream *audio_stream = ifmt_ctx->streams[audioindex];
 54     printf("----- Audio info:\n");
 55     printf("index: %d\n", audio_stream->index); // 序列号
 56     printf("samplarate: %d Hz\n", audio_stream->codecpar->sample_rate); // 采样率
 57     printf("sampleformat: %d\n", audio_stream->codecpar->format); // 采样格式 AV_SAMPLE_FMT_FLTP:8
 58     printf("audio codec: %d\n", audio_stream->codecpar->codec_id); // 编码格式 AV_CODEC_ID_MP3:86017 AV_CODEC_ID_AAC:86018
 59     if (audio_stream->duration != AV_NOPTS_VALUE) {
 60         int audio_duration = audio_stream->duration * av_q2d(audio_stream->time_base);
 61         printf("audio duration: %02d:%02d:%02d\n",
 62                audio_duration / 3600, (audio_duration % 3600) / 60, (audio_duration % 60));
 63     }
 64 
 65     // 视频
 66     int videoindex = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
 67     if (videoindex < 0) {
 68         printf("av_find_best_stream %s eror.", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
 69         return -1;
 70     }
 71     AVStream *video_stream = ifmt_ctx->streams[videoindex];
 72     printf("----- Video info:\n");
 73     printf("index: %d\n", video_stream->index); // 序列号
 74     printf("fps: %lf\n", av_q2d(video_stream->avg_frame_rate)); // 帧率
 75     printf("width: %d, height:%d \n", video_stream->codecpar->width, video_stream->codecpar->height);
 76     printf("video codec: %d\n", video_stream->codecpar->codec_id); // 编码格式 AV_CODEC_ID_H264: 27
 77     if (video_stream->duration != AV_NOPTS_VALUE) {
 78         int video_duration = video_stream->duration * av_q2d(video_stream->time_base);
 79         printf("audio duration: %02d:%02d:%02d\n",
 80                video_duration / 3600, (video_duration % 3600) / 60, (video_duration % 60));
 81     }
 82 
 83 // 5.提取码流
 84     AVPacket *pkt = av_packet_alloc();
 85     int pkt_count = 0;
 86     int print_max_count = 10;
 87     printf("\n-----av_read_frame start\n");
 88     while (1)
 89     {
 90         ret = av_read_frame(ifmt_ctx, pkt);
 91         if (ret < 0) {
 92             printf("av_read_frame end\n");
 93             break;
 94         }
 95 
 96         if(pkt_count++ < print_max_count)
 97         {
 98             if (pkt->stream_index == audioindex)
 99             {
100                 printf("audio pts: %lld\n", pkt->pts);
101                 printf("audio dts: %lld\n", pkt->dts);
102                 printf("audio size: %d\n", pkt->size);
103                 printf("audio pos: %lld\n", pkt->pos);
104                 printf("audio duration: %lf\n\n",
105                        pkt->duration * av_q2d(ifmt_ctx->streams[audioindex]->time_base));
106             }
107             else if (pkt->stream_index == videoindex)
108             {
109                 printf("video pts: %lld\n", pkt->pts);
110                 printf("video dts: %lld\n", pkt->dts);
111                 printf("video size: %d\n", pkt->size);
112                 printf("video pos: %lld\n", pkt->pos);
113                 printf("video duration: %lf\n\n",
114                        pkt->duration * av_q2d(ifmt_ctx->streams[videoindex]->time_base));
115             }
116             else
117             {
118                 printf("unknown stream_index:\n", pkt->stream_index);
119             }
120         }
121         av_packet_unref(pkt);
122     }
123 
124 // 6.结束
125     if(pkt)
126         av_packet_free(&pkt);
127     if(ifmt_ctx)
128         avformat_close_input(&ifmt_ctx);
129 
130 
131     getchar(); //加上这一句,防止程序打印完信息马上退出
132     return 0;
133 }

在linux环境中编译执行如下:

输出如下:

 1 in_filename = 1234.flv
 2 
 3 ==== av_dump_format in_filename:believe.flv ===
 4 Input #0, flv, from '1234.flv':
 5   Metadata:
 6     major_brand     : isom
 7     minor_version   : 512
 8     compatible_brands: isomiso2avc1mp41
 9     comment         : www.ieway.cn
10     encoder         : Lavf58.29.100
11   Duration: 00:03:42.53, start: 0.000000, bitrate: 286 kb/s
12     Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1920x1080, 150 kb/s, 14.46 fps, 15 tbr, 1k tbn, 30 tbc
13     Stream #0:1: Audio: aac (LC), 48000 Hz, stereo, fltp, 128 kb/s
14 
15 ==== av_dump_format finish =======
16 
17 media name:believe.flv
18 stream number:2
19 media average ratio:279kbps
20 audio duration: 00:03:42
21 
22 ----- Audio info:
23 index: 1
24 samplarate: 48000 Hz
25 sampleformat: 8
26 audio codec: 86018
27 ----- Video info:
28 index: 0
29 fps: 14.464286
30 width: 1920, height:1080
31 video codec: 27
32 
33 -----av_read_frame start
34 audio pts: 0
35 audio dts: 0
36 audio size: 341
37 audio pos: 502
38 audio duration: 0.021000
39 
40 video pts: 14
41 video dts: 14
42 video size: 66736
43 video pos: 860
44 video duration: 0.066000
45 
46 audio pts: 21
47 audio dts: 21
48 audio size: 341
49 audio pos: 67616
50 audio duration: 0.021000
51 
52 audio pts: 43
53 audio dts: 43
54 audio size: 342
55 audio pos: 67974
56 audio duration: 0.021000
57 
58 audio pts: 64
59 audio dts: 64
60 audio size: 341
61 audio pos: 68333
62 audio duration: 0.021000
63 
64 video pts: 81
65 video dts: 81
66 video size: 580
67 video pos: 68691
68 video duration: 0.066000
69 
70 audio pts: 85
71 audio dts: 85
72 audio size: 341
73 audio pos: 69291
74 audio duration: 0.021000
75 
76 audio pts: 107
77 audio dts: 107
78 audio size: 342
79 audio pos: 69649
80 audio duration: 0.021000
81 
82 audio pts: 128
83 audio dts: 128
84 audio size: 341
85 audio pos: 70008
86 audio duration: 0.021000
87 
88 video pts: 147
89 video dts: 147
90 video size: 11289
91 video pos: 70366
92 video duration: 0.066000 
93 av_read_frame end

 

posted @ 2021-06-29 09:49  封锁记忆  阅读(284)  评论(0)    收藏  举报