使用ffmpeg推流

使用ffmpeg推流

本文主要参考来自雷霄骅的博客,使用nginx测是RTMP推流。
测试环境: ubuntu + nginx + vlc

  • 使用头文件:
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
  • 输入和输出:
    通常我们使用ffmpeg输入和输出都是文件系统,现在要实现推流到nginx RTMP服务器,所以输出路径是一个RTMP协议URL:out_filename = "rtmp://localhost:1935/live1/553"; 同时必须调用函数 av_register_all(); avformat_network_init();
    打开网络, 注册av编解码器。
    //输入(Input)

    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
        printf( "Could not open input file.");
        goto end;
    }
    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
        printf( "Failed to retrieve input stream information");
        goto end;
    }

    int videoindex=-1;
    for(i=0; i<ifmt_ctx->nb_streams; i++) 
        if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
            videoindex=i;
            break;
        }

    av_dump_format(ifmt_ctx, 0, in_filename, 0);
    //输出(Output)
    
    avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename); //RTMP
    //avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDP

    if (!ofmt_ctx) {
        printf( "Could not create output context\n");
        ret = AVERROR_UNKNOWN;
        goto end;
    }
    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;
            goto end;
        }
        //复制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");
            goto end;
        }
        out_stream->codec->codec_tag = 0;
        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
            out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }
    //Dump Format------------------
    av_dump_format(ofmt_ctx, 0, out_filename, 1);
  • avio_open 函数和 avio_open2 函数
int avio_open (AVIOContext **s, const char *url, int flags);
int avio_open2 (AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary ** options);

这两个函数的flags参数类似Linux下的open函数,它的Value是:

AVIO_FLAG_READ
AVIO_FLAG_WRITE
AVIO_FLAG_READ_WRITE

avio_xx 具体函数手册上很详细,用法和Linux编程类型,常用的函数还有avio_close, avio_read, avio_write等,更多...
现在,使用avio_open函数打开rtmp地址, 同时写入文件头:

if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
    if (ret < 0) {
        printf( "Could not open output URL '%s'", out_filename);
    }
}
//写文件头(Write file header)
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
    printf( "Error occurred when opening output URL\n");
}
  • 读取输入帧和写入输出帧到URL流上
ret = av_read_frame(ifmt_ctx, &pkt);
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
  • 最后写文件尾和关闭IO
av_write_trailer(ofmt_ctx);
avio_close(ofmt_ctx->pb);

转载于:https://www.cnblogs.com/ikaka/p/4863526.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值