zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", ifilename, buf);
            avformat_close_input(&ifmt_ctx);
            return -1;
        }
    
    
    // 3.打印总体信息
        printf_s("
    ==== av_dump_format in_filename:%s ===
    ", ifilename);
        av_dump_format(ifmt_ctx, 0, ifilename, 0);
        printf_s("
    ==== av_dump_format finish =======
    
    ");
        printf("media name:%s
    ", ifmt_ctx->url);
        printf("stream number:%d
    ", ifmt_ctx->nb_streams); //  nb_streams媒体流数量
        printf("media average ratio:%lldkbps
    ",(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
    ",
               total_seconds / 3600, (total_seconds % 3600) / 60, (total_seconds % 60));
        printf("
    ");
    
    // 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:
    ");
        printf("index: %d
    ", audio_stream->index); // 序列号
        printf("samplarate: %d Hz
    ", audio_stream->codecpar->sample_rate); // 采样率
        printf("sampleformat: %d
    ", audio_stream->codecpar->format); // 采样格式 AV_SAMPLE_FMT_FLTP:8
        printf("audio codec: %d
    ", 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
    ",
                   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:
    ");
        printf("index: %d
    ", video_stream->index); // 序列号
        printf("fps: %lf
    ", av_q2d(video_stream->avg_frame_rate)); // 帧率
        printf(" %d, height:%d 
    ", video_stream->codecpar->width, video_stream->codecpar->height);
        printf("video codec: %d
    ", 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
    ",
                   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("
    -----av_read_frame start
    ");
        while (1)
        {
            ret = av_read_frame(ifmt_ctx, pkt);
            if (ret < 0) {
                printf("av_read_frame end
    ");
                break;
            }
    
            if(pkt_count++ < print_max_count)
            {
                if (pkt->stream_index == audioindex)
                {
                    printf("audio pts: %lld
    ", pkt->pts);
                    printf("audio dts: %lld
    ", pkt->dts);
                    printf("audio size: %d
    ", pkt->size);
                    printf("audio pos: %lld
    ", pkt->pos);
                    printf("audio duration: %lf
    
    ",
                           pkt->duration * av_q2d(ifmt_ctx->streams[audioindex]->time_base));
                }
                else if (pkt->stream_index == videoindex)
                {
                    printf("video pts: %lld
    ", pkt->pts);
                    printf("video dts: %lld
    ", pkt->dts);
                    printf("video size: %d
    ", pkt->size);
                    printf("video pos: %lld
    ", pkt->pos);
                    printf("video duration: %lf
    
    ",
                           pkt->duration * av_q2d(ifmt_ctx->streams[videoindex]->time_base));
                }
                else
                {
                    printf("unknown stream_index:
    ", 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
     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
  • 相关阅读:
    Redis和Memcache区别,优缺点对比
    C# 修改Config文件,增删查改
    SQL SERVER-时间戳(timestamp)与时间格式(datetime)互相转换
    post数据时报错:远程服务器返回错误: (400) 错误的请求。
    Win10 通过附加进程调试时出现“此任务要求应用程序具有提升的权限”
    谈谈技术原则,技术学习方法,代码阅读及其它
    C# 对象与JSON字符串互相转换的三种方式
    JSON.stringify 语法实例讲解
    前端Json对象与Json字符串互转(4种转换方式)
    Razor引擎学习:RenderBody,RenderPage和RenderSection
  • 原文地址:https://www.cnblogs.com/vczf/p/13541559.html
Copyright © 2011-2022 走看看