FFmpeg简单使用:解封装 ---- 基本流程

=====================================================

FFmpeg简单使用:解封装 ---- 基本流程

FFmpeg简单使用:解封装 ---- 提取aac

FFmpeg简单使用:音频解码 ---- 提取pcm

FFmpeg简单使用:视频解码 ---- 提取yuv

FFmpeg简单使用:音频编码 ---- pcm转aac

FFmpeg简单使用:视频编码 ---- YUV转H264

FFmpeg简单使用:过滤器 ---- 视频过滤

FFmpeg简单使用:过滤器 ---- 视频过滤2

FFmpeg简单使用:过滤器 ---- h264_mp4toannexb

FFmpeg简单使用:解封装h264 ---- 提取SPS PPS

=====================================================

解封装流程

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

 

编码:

#include <stdio.h>
#include <libavformat/avformat.h>

int main(int argc, char **argv)
{

// 1. 打开文件
    const char *ifilename = "believe.flv";
    printf("in_filename = %s\n", ifilename);
    // AVFormatContext是描述一个媒体文件或媒体流的构成和基本信息的结构体
    AVFormatContext *ifmt_ctx = NULL;           // 输入文件的demux
    // 打开文件,主要是探测协议类型,如果是网络文件则创建网络链接
    int ret = avformat_open_input(&ifmt_ctx, ifilename, NULL, NULL);
    if (ret < 0) {
        char buf[1024] = {0};
        av_strerror(ret, buf, sizeof (buf) - 1);
        printf("open %s failed: %s\n", ifilename, buf);
        return -1;
    }

// 2. 读取码流信息
    ret = avformat_find_stream_info(ifmt_ctx, NULL);
    if (ret < 0)  //如果打开媒体文件失败,打印失败原因
    {
        char buf[1024] = { 0 };
        av_strerror(ret, buf, sizeof(buf) - 1);
        printf("avformat_find_stream_info %s failed:%s\n", ifilename, buf);
        avformat_close_input(&ifmt_ctx);
        return -1;
    }


// 3.打印总体信息
    printf_s("\n==== av_dump_format in_filename:%s ===\n", ifilename);
    av_dump_format(ifmt_ctx, 0, ifilename, 0);
    printf_s("\n==== av_dump_format finish =======\n\n");
    printf("media name:%s\n", ifmt_ctx->url);
    printf("stream number:%d\n", ifmt_ctx->nb_streams); //  nb_streams媒体流数量
    printf("media average ratio:%lldkbps\n",(int64_t)(ifmt_ctx->bit_rate/1024)); //  媒体文件的码率,单位为bps
    // duration: 媒体文件时长,单位微妙
    int total_seconds = (ifmt_ctx->duration) / AV_TIME_BASE;  // 1000us = 1ms, 1000ms = 1秒
    printf("audio duration: %02d:%02d:%02d\n",
           total_seconds / 3600, (total_seconds % 3600) / 60, (total_seconds % 60));
    printf("\n");

// 4.读取码流信息
    // 音频
    int audioindex = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (audioindex < 0) {
        printf("av_find_best_stream %s eror.", av_get_media_type_string(AVMEDIA_TYPE_AUDIO));
        return -1;
    }
    AVStream *audio_stream = ifmt_ctx->streams[audioindex];
    printf("----- Audio info:\n");
    printf("index: %d\n", audio_stream->index); // 序列号
    printf("samplarate: %d Hz\n", audio_stream->codecpar->sample_rate); // 采样率
    printf("sampleformat: %d\n", audio_stream->codecpar->format); // 采样格式 AV_SAMPLE_FMT_FLTP:8
    printf("audio codec: %d\n", audio_stream->codecpar->codec_id); // 编码格式 AV_CODEC_ID_MP3:86017 AV_CODEC_ID_AAC:86018
    if (audio_stream->duration != AV_NOPTS_VALUE) {
        int audio_duration = audio_stream->duration * av_q2d(audio_stream->time_base);
        printf("audio duration: %02d:%02d:%02d\n",
               audio_duration / 3600, (audio_duration % 3600) / 60, (audio_duration % 60));
    }

    // 视频
    int videoindex = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    if (videoindex < 0) {
        printf("av_find_best_stream %s eror.", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
        return -1;
    }
    AVStream *video_stream = ifmt_ctx->streams[videoindex];
    printf("----- Video info:\n");
    printf("index: %d\n", video_stream->index); // 序列号
    printf("fps: %lf\n", av_q2d(video_stream->avg_frame_rate)); // 帧率
    printf("width: %d, height:%d \n", video_stream->codecpar->width, video_stream->codecpar->height);
    printf("video codec: %d\n", video_stream->codecpar->codec_id); // 编码格式 AV_CODEC_ID_H264: 27
    if (video_stream->duration != AV_NOPTS_VALUE) {
        int video_duration = video_stream->duration * av_q2d(video_stream->time_base);
        printf("audio duration: %02d:%02d:%02d\n",
               video_duration / 3600, (video_duration % 3600) / 60, (video_duration % 60));
    }

// 5.提取码流
    AVPacket *pkt = av_packet_alloc();
    int pkt_count = 0;
    int print_max_count = 10;
    printf("\n-----av_read_frame start\n");
    while (1)
    {
        ret = av_read_frame(ifmt_ctx, pkt);
        if (ret < 0) {
            printf("av_read_frame end\n");
            break;
        }

        if(pkt_count++ < print_max_count)
        {
            if (pkt->stream_index == audioindex)
            {
                printf("audio pts: %lld\n", pkt->pts);
                printf("audio dts: %lld\n", pkt->dts);
                printf("audio size: %d\n", pkt->size);
                printf("audio pos: %lld\n", pkt->pos);
                printf("audio duration: %lf\n\n",
                       pkt->duration * av_q2d(ifmt_ctx->streams[audioindex]->time_base));
            }
            else if (pkt->stream_index == videoindex)
            {
                printf("video pts: %lld\n", pkt->pts);
                printf("video dts: %lld\n", pkt->dts);
                printf("video size: %d\n", pkt->size);
                printf("video pos: %lld\n", pkt->pos);
                printf("video duration: %lf\n\n",
                       pkt->duration * av_q2d(ifmt_ctx->streams[videoindex]->time_base));
            }
            else
            {
                printf("unknown stream_index:\n", pkt->stream_index);
            }
        }
        av_packet_unref(pkt);
    }

// 6.结束
    if(pkt)
        av_packet_free(&pkt);
    if(ifmt_ctx)
        avformat_close_input(&ifmt_ctx);


    getchar(); //加上这一句,防止程序打印完信息马上退出
    return 0;
}

 

输出:

in_filename = believe.flv

==== av_dump_format in_filename:believe.flv ===
Input #0, flv, from 'believe.flv':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    comment         : www.ieway.cn
    encoder         : Lavf58.29.100
  Duration: 00:03:42.53, start: 0.000000, bitrate: 286 kb/s
    Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1920x1080, 150 kb/s, 14.46 fps, 15 tbr, 1k tbn, 30 tbc
    Stream #0:1: Audio: aac (LC), 48000 Hz, stereo, fltp, 128 kb/s

==== av_dump_format finish =======

media name:believe.flv
stream number:2
media average ratio:279kbps
audio duration: 00:03:42

----- Audio info:
index: 1
samplarate: 48000 Hz
sampleformat: 8
audio codec: 86018
----- Video info:
index: 0
fps: 14.464286
width: 1920, height:1080
video codec: 27

-----av_read_frame start
audio pts: 0
audio dts: 0
audio size: 341
audio pos: 502
audio duration: 0.021000

video pts: 14
video dts: 14
video size: 66736
video pos: 860
video duration: 0.066000

audio pts: 21
audio dts: 21
audio size: 341
audio pos: 67616
audio duration: 0.021000

audio pts: 43
audio dts: 43
audio size: 342
audio pos: 67974
audio duration: 0.021000

audio pts: 64
audio dts: 64
audio size: 341
audio pos: 68333
audio duration: 0.021000

video pts: 81
video dts: 81
video size: 580
video pos: 68691
video duration: 0.066000

audio pts: 85
audio dts: 85
audio size: 341
audio pos: 69291
audio duration: 0.021000

audio pts: 107
audio dts: 107
audio size: 342
audio pos: 69649
audio duration: 0.021000

audio pts: 128
audio dts: 128
audio size: 341
audio pos: 70008
audio duration: 0.021000

video pts: 147
video dts: 147
video size: 11289
video pos: 70366
video duration: 0.066000

av_read_frame end

 

posted @ 2020-08-21 16:04  Vzf  阅读(2715)  评论(0编辑  收藏  举报