1. 程式人生 > >使用ffmpeg實現RTMP的直播推流功能

使用ffmpeg實現RTMP的直播推流功能

其中檔名in_filename為輸入檔名,out_filename為輸出rtmp地址。


void UpliveThread::uplive_process( )
{
    AVOutputFormat *p_ofmt = NULL;
    AVFormatContext *p_ifmt_ctx = NULL, *p_ofmt_ctx = NULL;
    AVIOContext *p_avio_ctx;
    AVInputFormat  *p_av_input_fmt;
    AVPacket pkt;
    const char *in_filename, *out_filename
; unsigned char *p_avio_buffer; int n_ret, i; int n_video_index = -1; int n_frame_index = 0; int64_t n_start_time = 0; in_filename = "視訊檔名.flv"; out_filename = "rtmp://地址"; av_register_all(); avformat_network_init(); while ( false == mb_convert ) { QThread::msleep(35
); } #ifdef FILE_STREAM if( ( n_ret = avformat_open_input( &p_ifmt_ctx, in_filename, 0, 0) ) < 0 ) { qDebug()<<"could not open input file."; goto end; } if( ( n_ret = avformat_find_stream_info( p_ifmt_ctx, 0 ) ) < 0 ) { qDebug()<<"failed to retrieve input stream information"
; goto end; } for( i = 0; i < p_ifmt_ctx->nb_streams; i++ ) { if( p_ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) { n_video_index = i; break; } } #endif av_dump_format( p_ifmt_ctx, 0, in_filename, 0 ); avformat_alloc_output_context2( &p_ofmt_ctx, NULL, "flv", out_filename ); if( !p_ofmt_ctx ) { qDebug()<<"could not create output context"; n_ret = AVERROR_UNKNOWN; goto end; } p_ofmt = p_ofmt_ctx->oformat; for( int i = 0; i<p_ifmt_ctx->nb_streams; i++ ) { AVStream *in_stream = p_ifmt_ctx->streams[i]; AVStream *out_stream = avformat_new_stream( p_ofmt_ctx, in_stream->codec->codec ); if( !out_stream ) { qDebug()<<"failed allocating output stream"; n_ret = AVERROR_UNKNOWN; goto end; } n_ret = avcodec_copy_context( out_stream->codec, in_stream->codec ); if( n_ret < 0 ) { qDebug()<<"failed to copy context from input to output stream codec context"; goto end; } out_stream->codec->codec_tag = 0; if( p_ofmt_ctx->oformat->flags && AVFMT_GLOBALHEADER ) { out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } } av_dump_format( p_ofmt_ctx, 0, out_filename, 1 ); qDebug()<<"avio open before"; if( !( p_ofmt->flags & AVFMT_NOFILE ) ) { n_ret = avio_open( &p_ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE ); qDebug()<<"p_ofmt_ctx->pb: "<<p_ofmt_ctx->pb<<n_ret; if( n_ret < 0 ) { qDebug()<<"could not open output URL: "<<out_filename; goto end; } } n_ret = avformat_write_header( p_ofmt_ctx, NULL ); if( n_ret < 0 ) { qDebug()<<"error ocurred when opening output URL"; goto end; } n_start_time = av_gettime(); qDebug()<<"avio open after"; while( 1 ) { AVStream *in_stream, *out_stream; n_ret = av_read_frame( p_ifmt_ctx, &pkt ); if( n_ret < 0 ) { break; } if( pkt.pts == AV_NOPTS_VALUE ) { AVRational time_base1 = p_ifmt_ctx->streams[n_video_index]->time_base; int64_t n_calc_duration = ( double )AV_TIME_BASE/av_q2d( p_ifmt_ctx->streams[n_video_index]->r_frame_rate); pkt.pts = ( double )( n_frame_index * n_calc_duration )/( double )( av_q2d(time_base1)*AV_TIME_BASE ); pkt.dts = pkt.pts; pkt.duration = ( double )n_calc_duration/( double )( av_q2d( time_base1 )*AV_TIME_BASE ); } if( pkt.stream_index == n_video_index ) { AVRational time_base = p_ifmt_ctx->streams[n_video_index]->time_base; AVRational time_base_q = { 1, AV_TIME_BASE }; int64_t n_pts_time = av_rescale_q( pkt.dts, time_base, time_base_q ); int64_t n_now_time = av_gettime() - n_start_time; if( n_pts_time > n_now_time ) { av_usleep( n_pts_time - n_now_time ); } } in_stream = p_ifmt_ctx->streams[pkt.stream_index]; out_stream = p_ofmt_ctx->streams[pkt.stream_index]; 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_INF | AV_ROUND_PASS_MINMAX ) ); pkt.duration = av_rescale_q( pkt.duration, in_stream->time_base, out_stream->time_base ); pkt.pos = -1; printf( "Write 1 Packet. size:%5d\tpts:%lld\t duration:%lld\n", pkt.size, pkt.pts, pkt.duration ); if( pkt.stream_index == n_video_index ) { qDebug()<<"send video frames to output URL: "<<n_frame_index; n_frame_index++; } n_ret = av_interleaved_write_frame( p_ofmt_ctx, &pkt ); if( n_ret < 0 ) { qDebug()<<"error muxing packet"; break; } av_free_packet( &pkt ); } av_write_trailer( p_ofmt_ctx ); end: qDebug()<<"end"; avformat_close_input( &p_ifmt_ctx ); if( p_ofmt_ctx && !(p_ofmt->flags & AVFMT_NOFILE ) ) { avio_close( p_ofmt_ctx->pb ); } avformat_free_context( p_ofmt_ctx ); if( n_ret < 0 && n_ret != AVERROR_EOF ) { qDebug()<<"error occurred"; return ; } return; }