• Centos7编译运行封装格式转换器


    安装依赖库

    yum -y install gcc gcc-c++ gdb automake nasm
    

    下载源代码并编译

    git clone https://gitee.com/mirrors/ffmpeg.git
    cd ffmpeg
    ./configure --prefix=/usr/local/ffmpeg
    make
    make install
    

    写测试程序

    复制雷霄骅的代码:https://blog.csdn.net/leixiaohua1020/article/details/25422685
    修改之后如下:

    /*
     *最简单的基于FFmpeg的封装格式转换器
     *Simplest FFmpeg Remuxer
     *
     *雷霄骅 Lei Xiaohua
     *leixiaohua1020@126.com
     *中国传媒大学/数字电视技术
     *Communication University of China / Digital TV Technology
     *http://blog.csdn.net/leixiaohua1020
     *
     *本程序实现了视频封装格式之间的转换。
     *需要注意的是本程序并不改变视音频的编码格式。
     *
     * This software converts a media file from one container format
     * to another container format without encoding/decoding video files.
     */
    #include <ctype.h>
    #include <string.h>
    #include <math.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    #include <stdint.h>
    
    #if HAVE_IO_H
    #include <io.h>
    #endif
    #if HAVE_UNISTD_H
    #include <unistd.h>
    #endif
    
    extern "C"
    {
    #include "libavformat/avformat.h"
    };
    
    
    int main(int argc, char* argv[])
    {
        AVOutputFormat *ofmt = NULL;
        //输入对应一个AVFormatContext,输出对应一个AVFormatContext
        //(Input AVFormatContext and Output AVFormatContext)
        AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
        AVPacket pkt;
        const char *in_filename, *out_filename;
        int ret, i;
        if (argc < 3) {
            printf("usage: %s input output
    "
                "Remux a media file with libavformat and libavcodec.
    "
                "The output format is guessed according to the file extension.
    "
                "Modified by Lei Xiaohua, leixiaohua1020@126.com
    "
                "Communication University of China / Digital TV Technology
    "
                "http://blog.csdn.net/leixiaohua1020", argv[0]);
            return 1;
        }
        in_filename  = argv[1];//输入文件名(Input file URL)
        out_filename = argv[2];//输出文件名(Output file URL)
        av_register_all();
        do{
            //输入(Input)
            if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
                printf( "Could not open input file.");
                break;
            }
            if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
                printf( "Failed to retrieve input stream information");
                break;
            }
            av_dump_format(ifmt_ctx, 0, in_filename, 0);
            //输出(Output)
            //avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename);
            avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
            if (!ofmt_ctx) {
                printf( "Could not create output context
    ");
                ret = AVERROR_UNKNOWN;
                break;
            }
            ofmt = ofmt_ctx->oformat;
            for (i = 0; i < ifmt_ctx->nb_streams; i++) {
                //根据输入流创建输出流(Create output AVStream according to input AVStream)
                AVStream *in_stream = ifmt_ctx->streams[i];
                AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
                if (!out_stream) {
                    printf( "Failed allocating output stream
    ");
                    ret = AVERROR_UNKNOWN;
                    break;
                }
                //复制AVCodecContext的设置(Copy the settings of AVCodecContext)
                ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
                if (ret < 0) {
                    printf( "Failed to copy context from input to output stream codec context
    ");
                    break;
                }
                out_stream->codec->codec_tag = 0;
                if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
                    out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
            }
            if (ret < 0){
                break;
            }
            //输出一下格式------------------
            av_dump_format(ofmt_ctx, 0, out_filename, 1);
            //打开输出文件(Open output file)
            if (!(ofmt->flags & AVFMT_NOFILE)) {
                ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
                if (ret < 0) {
                    printf( "Could not open output file '%s'", out_filename);
                    break;
                }
            }
            //写文件头(Write file header)
            ret = avformat_write_header(ofmt_ctx, NULL);
            if (ret < 0) {
                printf( "Error occurred when opening output file
    ");
                break;
            }
        
            int frame_index=0;
            while (1) {
                AVStream *in_stream, *out_stream;
                //获取一个AVPacket(Get an AVPacket)
                ret = av_read_frame(ifmt_ctx, &pkt);
                if (ret < 0)
                    break;
                in_stream  = ifmt_ctx->streams[pkt.stream_index];
                out_stream = ofmt_ctx->streams[pkt.stream_index];
                /* copy packet */
                //转换PTS/DTS(Convert PTS/DTS)
                pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
                pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
                pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
                pkt.pos = -1;
                //写入(Write)
                ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
                if (ret < 0) {
                    printf( "Error muxing packet
    ");
                    continue;
                }
                printf("Write %8d frames to output file
    ",frame_index);
                av_free_packet(&pkt);
                frame_index++;
            }
            //写文件尾(Write file trailer)
            av_write_trailer(ofmt_ctx);
        }while(0);
        avformat_close_input(&ifmt_ctx);
        /* close output */
        if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
            avio_close(ofmt_ctx->pb);
        avformat_free_context(ofmt_ctx);
        if (ret < 0 && ret != AVERROR_EOF) {
            printf( "Error occurred.
    ");
            return -1;
        }
        return 0;
    }
    
    

    编译

    g++ simplest_ffmpeg_remuxer.cpp -g -o simplest_ffmpeg_remuxer -I /usr/local/ffmpeg/include -L /usr/local/ffmpeg/lib -lavformat -lavcodec -lavutil -lswscale -lswresample -lavfilter -lpthread
    

    运行

    ./simplest_ffmpeg_remuxer "udp://127.0.0.1:1234" "rtmp://192.168.0.33:1935/hls/testcp"
    

    出现的问题

    1.编译过程中会报一些错"undefined reference"

    /usr/local/ffmpeg/lib/libavformat.a(avienc.o): In function `avi_write_header':
    /home/ffmpeg/ffmpeg/libavformat/avienc.c:317: undefined reference to `ceil'
    /usr/local/ffmpeg/lib/libavformat.a(matroskaenc.o): In function `mkv_write_trailer':
    /home/ffmpeg/ffmpeg/libavformat/matroskaenc.c:2591: undefined reference to `fmod'
    /usr/local/ffmpeg/lib/libavcodec.a(aaccoder.o): In function `quantize_and_encode_band_cost_template':
    /home/ffmpeg/ffmpeg/libavcodec/aacenc_quantization.h:108: undefined reference to `cbrtf'
    /home/ffmpeg/ffmpeg/libavutil/display.c:38: undefined reference to `hypot'
    .......
    

    解决方法:
    检查编译参数是否写全,"-lavformat -lavcodec -lavutil -lswscale -lswresample -lavfilter -lpthread"

  • 相关阅读:
    Thymeleaf介绍和基本语法使用
    2020版idea及没有default Settings设置的idea,修改默认maven设置、本地仓库的方法
    创建springboot项目的两种方式
    2020版IDEA新建打开*.vue文件
    IDEA新手常用快捷键
    搭建一个maven的web项目
    eclipse、idea引入外部jar包教程
    序列化笔记
    转换流笔记
    缓冲流笔记
  • 原文地址:https://www.cnblogs.com/bugutian/p/14116701.html
Copyright © 2020-2023  润新知