zoukankan      html  css  js  c++  java
  • 使用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);
    
  • 相关阅读:
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 画图(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 相邻数对(暴力)
    Java实现 蓝桥杯 算法训练 Cowboys
    Java实现 蓝桥杯 算法训练 Cowboys
    55. Jump Game
    54. Spiral Matrix
    50. Pow(x, n)
  • 原文地址:https://www.cnblogs.com/ikaka/p/4863526.html
Copyright © 2011-2022 走看看