• 使用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编解码器。
    
    ```C
    	//输入(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
    ");
    		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
    ");
    			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
    ");
    			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
    ");
    }
    
    • 读取输入帧和写入输出帧到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);
    
  • 相关阅读:
    散列
    红黑树
    发散二叉搜索树
    二叉搜索树的删除和联结
    平衡树
    二叉搜索树的划分
    在二叉搜索树的根进行插入
    paper169:2020CVPR文章解读:nestedVAE:Isolating common facters via weak supervision
    paper 168: 2018-FATTEN 论文解析-feature space transfer for data augmentation
    paper 167:GPU的使用Theano之tutorial
  • 原文地址:https://www.cnblogs.com/ikaka/p/4863526.html
Copyright © 2020-2023  润新知