Title: Audio and video series five: FFMPEG RTMP push stream Ali Cloud forward VLC pull stream play

categories:[ffmpeg]

Tags: audio and Video Programming

date: 2021/11/30

Author: hackett

Wechat official account: Overtime Ape

In the first two parts of Nginx+ RTMP push stream server, we have configured the RTMP push stream service of Ali Cloud to set up, using THE PC software OBS to push stream to Ali cloud server, and then using Raytheon’s simplest ffMPEG based push stream, RTMP way push stream. Ali cloud server forward flow, VLC pull flow of the process to go again.

Links: the simplest FFmpeg based on flow apparatus for transporting the RTMP (for example) blog.csdn.net/leixiaohua1…

1. RTMP

RTMP is an acronym for Real Time Messaging Protocol. This protocol is based on TCP and is a protocol family, including RTMP and RTMPT/RTMPS/RTMPE. RTMP is a network protocol designed for real-time data communication. It is mainly used for audio, video and data communication between Flash/AIR platforms and streaming/interactive servers that support the RTMP protocol. Software supporting this protocol includes Adobe Media Server, Ultrant Media Server, Red5, etc. RTMP, like HTTP, belongs to the application layer of the TCP/IP four-tier model. — Baidu Encyclopedia

The role of the RTMP Streamer in a streaming media system can be illustrated in the following figure. First, the video data is sent to the streaming media Server (such as FMS, Red5, Wowza, etc.) in the form of RTMP. Then the client (generally Flash Player) can watch the real-time streaming by accessing the streaming media Server.

Second, the program flow chart

The RTMP package format is FLV. Therefore, when specifying the output streaming media, you need to specify the encapsulation format as FLV. Similarly, other streaming media protocols also need to specify their encapsulation formats. For example, if UDP push streaming media is used, you can set the encapsulation format to MPEGTS.

Av_register_all () : Registers all FFmpeg codecs.

Avformat_network_init () : initializes the Network.

Avformat_open_input () : Input (Input).

Avformat_find_stream_info () : Finds stream information.

Avformat_alloc_output_context2 () : Allocates the output AVFormatContext.

Avcodec_copy_context () : Copies the Settings of AVCodecContext.

Avformat_write_header () : Write file header.

Av_read_frame () : Gets an AVPacket.

Av_rescale_q_rnd () : Convert PTS/DTS (Convert PTS/DTS)

Av_interleaved_write_frame () : writes the end of a file.

Three, code,

#include <iostream>

extern "C" {// contains the C header file
#include "libavformat/avformat.h" 
#include "libavutil/time.h"
};

int main(int argc, char* argv[]) {
 AVOutputFormat* ofmt = NULL;
 // Input corresponds to an AVFormatContext, output corresponds to an AVFormatContext
 // (Input AVFormatContext and Output AVFormatContext)
 AVFormatContext* ifmt_ctx = NULL, * ofmt_ctx = NULL;
 AVPacket pkt;
 const char* in_filename, * out_filename;
 int ret, i;
 int videoindex = - 1;
 int frame_index = 0;
 int64_t start_time = 0;
 //in_filename = "cuc_ieschool.mov";
 //in_filename = "cuc_ieschool.mkv";
 //in_filename = "cuc_ieschool.ts";
 //in_filename = "cuc_ieschool.mp4";
 //in_filename = "cuc_ieschool.h264";
 in_filename = "./ouput_1min.flv";// Enter the URL (Input file URL)
 //in_filename = "shanghai03_p.h264";

 //out_filename = "rtmp://localhost/publishlive/livestream"; // Output URL (RTMP URL)
 out_filename = "RTMP :// Ali cloud server IP:1935/live";// Output URL (RTMP URL)
 //out_filename = "rtp://233.233.233.233:6666";//输出 URL(Output URL)[UDP]

 // Register all FFmpeg codecs
 av_register_all(a);//Network
 avformat_network_init(a);// 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;
 }

 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 (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;
  }
  // 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 |= AV_CODEC_FLAG_GLOBAL_HEADER;
 }
 //Dump Format
 av_dump_format(ofmt_ctx, 0, out_filename, 1);
 // Open output URL
 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);
   gotoend; }}// Write file header
 ret = avformat_write_header(ofmt_ctx, NULL);
 if (ret < 0) {
  printf("Error occurred when opening output URL\n");
  goto end;
 }

 start_time = av_gettime(a);while (1) {
  AVStream* in_stream, * out_stream;
  // Get an AVPacket
  ret = av_read_frame(ifmt_ctx, &pkt);
  if (ret < 0)
   break;
  //FIX: No PTS (Example: Raw H.264)
  //Simple Write PTS
  if (pkt.pts == AV_NOPTS_VALUE) {
   //Write PTS
   AVRational time_base1 = ifmt_ctx->streams[videoindex]->time_base;
   //Duration between 2 frames (us)
   int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate);
   //Parameters
   pkt.pts = (double)(frame_index * calc_duration) / (double) (av_q2d(time_base1) * AV_TIME_BASE);
   pkt.dts = pkt.pts;
   pkt.duration = (double)calc_duration / (double) (av_q2d(time_base1) * AV_TIME_BASE);
  }
  / / Important: Delay time Delay
  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];
  /* copy packet */
  // Convert PTS/DTS (Convert PTS/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.dts = av_rescale_q_rnd(pkt.dts, 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;
  //Print to Screen
  if (pkt.stream_index == videoindex) {
   printf("Send %8d video frames to output URL\n", frame_index);
   frame_index++;
  }
  //ret = av_write_frame(ofmt_ctx, &pkt);
  ret = av_interleaved_write_frame(ofmt_ctx, &pkt);

  if (ret < 0) {
   printf("Error muxing packet\n");
   break;
  }

  av_free_packet(&pkt);

 }
 // Write file trailer
 av_write_trailer(ofmt_ctx);
end:
 avformat_close_input(&ifmt_ctx);
 /* close output */
 if(ofmt_ctx && ! (ofmt->flags & AVFMT_NOFILE))avio_close(ofmt_ctx->pb);
 avformat_free_context(ofmt_ctx);
 if (ret < 0&& ret ! = AVERROR_EOF) {printf("Error occurred.\n");
  return - 1;
 }
 return 0;
}
Copy the code

4. Operation results

If you think the article is good, you can give it a “triple link”, and the article will be synchronized to the following personal wechat official account [Overtime Ape].

I’m Hackett. I’ll see you next time