目录- 安装依赖库

安装依赖库

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
 *[email protected]
 *中国传媒大学/数字电视技术
 *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\n"
            "Remux a media file with libavformat and libavcodec.\n"
            "The output format is guessed according to the file extension.\n"
            "Modified by Lei Xiaohua, [email protected]\n"
            "Communication University of China / Digital TV Technology\n"
            "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\n");
            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\n");
                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\n");
                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\n");
            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\n");
                continue;
            }
            printf("Write %8d frames to output file\n",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.\n");
        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"


标签: Centos7, 封装, ffmpeg, ctx, ret, stream, 转换器, out, ofmt

相关文章推荐

添加新评论,含*的栏目为必填