FFMpeg rtmp 推送本地H264文件或mp4文件

#include<iostream>
#include <cstring>
#include <cstdlib>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/time.h>
#include <libavutil/imgutils.h>
}

using namespace std;

const char* input_file = "/mnt/hgfs/shareVM/welcom_to_beijing.h264";
// const char* input_file = "/mnt/hgfs/shareVM/welcom_to_beijing.mp4";
const char* output_rtmp_url = "rtmp://10.10.18.94:1935/live/test";

#define CODEC_FLAG_GLOBAL_HEADER 0x00400000

int main() {
    cout << "Hello World!" << endl;

    AVOutputFormat *ofmt = NULL;
    AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    AVPacket pkt;

    int videoindex = -1;
    int frame_index = 0;
    int64_t start_time = 0;

    av_register_all();
    avformat_network_init();

    if(avformat_open_input(&ifmt_ctx, input_file, 0, 0) < 0) {
        cout<<"could not open input file."<<endl;
        goto end;
    }

    if(avformat_find_stream_info(ifmt_ctx, 0) < 0) {
        cout<<"failed to retrieve input stream information"<<endl;
        goto end;
    }

    for(int 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, input_file, 0);

    avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", output_rtmp_url);
    if(!ofmt_ctx) {
        cout<<"could not create output context"<<endl;
        goto end;
    }

    ofmt = ofmt_ctx->oformat;
    for(int i=0;i<ifmt_ctx->nb_streams;i++) {
        AVStream *in_stream = ifmt_ctx->streams[i];
        AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
        if(!out_stream) {
            cout<<"failed allocating output stream"<<endl;
            goto end;
        }
        if(avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
            cout<<"failed to copy context from input to output stream codec context"<<endl;
            goto end;
        }
        out_stream->codec->codec_tag = 0;
        if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
            out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }

    av_dump_format(ofmt_ctx, 0, output_rtmp_url, 1);
    if(!(ofmt->flags & AVFMT_NOFILE)) {
        if(avio_open(&ofmt_ctx->pb, output_rtmp_url, AVIO_FLAG_WRITE) < 0) {
            cout<<"could not open output rtmp url."<<endl;
            goto end;
        }
    }

    if(avformat_write_header(ofmt_ctx, NULL) < 0) {
        cout<<"error occurred when opening output rtmp url."<<endl;
        goto end;
    }

    start_time = av_gettime();

    while (1) {
        AVStream *in_stream, *out_stream;

        if(av_read_frame(ifmt_ctx, &pkt) < 0)
            break;

        if(pkt.pts == AV_NOPTS_VALUE) {
            AVRational time_base1 = ifmt_ctx->streams[videoindex]->time_base;
            int64_t calc_duration = (double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate);
            pkt.dts = pkt.pts = (double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);

            pkt.duration = (double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
        }

        if(pkt.stream_index == videoindex) {
            AVRational time_base = ifmt_ctx->streams[videoindex]->time_base;
            AVRational time_base_q = {1, AV_TIME_BASE};
            int64_t pts_time = av_rescale_q(pkt.dts, time_base, time_base_q);
            int64_t now_time = av_gettime() - start_time;
            if(pts_time > now_time)
                av_usleep(pts_time - now_time);
        }

        in_stream = ifmt_ctx->streams[pkt.stream_index];
        out_stream = ofmt_ctx->streams[pkt.stream_index];

        pkt.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.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
        pkt.pos = -1;

        if(pkt.stream_index == videoindex) {
            cout<<"send "<<frame_index<<" video frame to output rtmp url."<<endl;
            frame_index++;
        }

        if(av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {
            cout<<"error muxing packet."<<endl;
            break;
        }

        av_free_packet(&pkt);
    }

    av_write_trailer(ofmt_ctx);

end:
    avformat_close_input(&ifmt_ctx);

    if(ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
        avio_close(ofmt_ctx->pb);
    avformat_free_context(ofmt_ctx);

    return 0;
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux上使用FFmpeg推流RTMP流为h264/PC的步骤如下: 1. 首先,确保你已经安装了FFmpeg。如果没有安装,可以使用以下命令进行安装: ``` sudo apt-get install ffmpeg ``` 2. 使用以下命令将h264视频流和PCMU音频流推送RTMP服务器: ``` ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -tune zerolatency -b:v 2000k -maxrate 2000k -bufsize 2000k -pix_fmt yuv420p -g 50 -c:a pcm_mulaw -ar 8000 -f flv rtmp://server/live/stream ``` 解释一下上述命令的参数: - `-re`:以实时速度读取输入文件。 - `-i input.mp4`:指定输入文件的路径和名称。 - `-c:v libx264`:使用libx264编码器进行视频编码。 - `-preset veryfast`:设置视频编码速度为veryfast。 - `-tune zerolatency`:设置视频编码器为零延迟模式。 - `-b:v 2000k`:设置视频的比特率为2000k。 - `-maxrate 2000k`:设置视频的最大比特率为2000k。 - `-bufsize 2000k`:设置视频的缓冲区大小为2000k。 - `-pix_fmt yuv420p`:设置像素格式为yuv420p。 - `-g 50`:设置关键帧间隔为50帧。 - `-c:a pcm_mulaw`:使用PCM mu-law编码器进行音频编码。 - `-ar 8000`:设置音频的采样率为8000Hz。 - `-f flv`:指定输出格式为FLV。 - `rtmp://server/live/stream`:指定RTMP服务器的URL和流名称。 请根据你的实际情况修改输入文件的路径和名称,以及RTMP服务器的URL和流名称。 希望以上信息对你有帮助!如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值