“*libRTMP study”的版本间的差异

来自个人维基
跳转至: 导航搜索
ffmpeg calling flow
 
(未显示1个用户的11个中间版本)
第44行: 第44行:
 
ffmpeg/libavformat/rtmpproto.c
 
ffmpeg/libavformat/rtmpproto.c
  
 +
<source lang="c">
 +
const URLProtocol ff_rtmp[e|s|t|te|ts]_protocol = {    \
 +
    .name          = rtmp[e|s|t|te|ts],                  \
 +
    .url_open2      = rtmp_open,                \
 +
    .url_read      = rtmp_read,                \
 +
    .url_read_seek  = rtmp_seek,                \
 +
    .url_read_pause = rtmp_pause,                \
 +
    .url_write      = rtmp_write,                \
 +
    .url_close      = rtmp_close,                \
 +
    .priv_data_size = sizeof(RTMPContext),      \
 +
    .flags          = URL_PROTOCOL_FLAG_NETWORK, \
 +
    .priv_data_class= &rtmp[e|s|t|te|ts]_class,          \
 +
};
 +
#define RTMP_PROTOCOL(rtmp[e|s|t|te|ts])
 +
static const AVClass rtmp[e|s|t|te|ts]##_class = {          \
 +
    .class_name = #rtmp[e|s|t|te|ts],                      \
 +
    .item_name  = av_default_item_name,          \
 +
    .option    = rtmp_options,                  \
 +
    .version    = LIBAVUTIL_VERSION_INT,        \
 +
}; 
 +
static const AVOption rtmp_options[] = {
 +
    {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
 +
    {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
 +
    {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
 +
    {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
 +
    {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
 +
    {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
 +
    {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
 +
    {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
 +
    {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
 +
    {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
 +
    {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
 +
    {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
 +
    {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
 +
    {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
 +
    {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
 +
    { NULL },
 +
};
  
 +
</source>
 +
declared in libformat/protocols.c
 +
<source lang="c">
 +
extern const URLProtocol ff_rtmp_protocol;
 +
extern const URLProtocol ff_rtmpe_protocol;
 +
extern const URLProtocol ff_rtmps_protocol;
 +
extern const URLProtocol ff_rtmpt_protocol;
 +
extern const URLProtocol ff_rtmpte_protocol;
 +
extern const URLProtocol ff_rtmpts_protocol;
 +
</source>
 +
libavformat/protocol_list.c
 +
<source lang="c">
 +
static const URLProtocol *url_protocols[] = {
 +
    &&ff_rtmp_protocol,
 +
    ....
 +
}
 +
</source>
 +
libavformat/makefile
 +
<source lang="c">
 +
OBJS-$(CONFIG_RTMP_PROTOCOL)  += rtmpproto.o rtmpdigest.o rtmppkt.o
 +
OBJS-$(CONFIG_LIBRTMP_PROTOCOL)          += librtmp.o
 +
OBJS-$(CONFIG_LIBRTMPE_PROTOCOL)        += librtmp.o
 +
OBJS-$(CONFIG_LIBRTMPS_PROTOCOL)        += librtmp.o
 +
OBJS-$(CONFIG_LIBRTMPT_PROTOCOL)        += librtmp.o
 +
OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL)        += librtmp.o
 +
 +
SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
 +
OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL)      += rtmpcrypt.o rtmpdigest.o rtmpdh.o
 +
OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL)      += rtmphttp.o
 +
</source>
 +
 +
ffmpeg/libavformat/rtmpproto.c
 +
<source lang="c">
 +
/**
 +
* Open RTMP connection and verify that the stream can be played.
 +
*
 +
* URL syntax: rtmp://server[:port][/app][/playpath][ keyword=value]...
 +
*/
 +
static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)
 +
 +
</source>
 +
ffmpeg/config.h
 +
<source lang="c">
 +
#define CONFI_RTMP_PROTOCOL 1
 +
</source>
 +
config.mak
 +
<source lang="c">
 +
CONFIG_RTMP_PROTOCOL=yes
 +
</source>
 +
 +
=ffmpeg calling flow =
 +
avformat_network_init
 +
ffmpeg_parse_options {//ffmpeg_opt.c
 +
  open_input_file {
 +
    avformat_open_input //utils.c
 +
    choose_decoder(AVCodec->id)
 +
  }
 +
  open_output_file {
 +
    init_output_filter
 +
    av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO)
 +
    avformat_query_codec
 +
    new_video_stream(idx)
 +
  }
 +
}
 +
transcode {
 +
  treancode_init
 +
  init_input_thread
 +
  while(not terminate) {
 +
 +
  }
 +
  free_input_threads
 +
  flush_encoder
 +
  exit
 +
}
 
Log:
 
Log:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] Setting codecpar->delay to 2 for stream st: 0
+
ffmpeg version N-94476-gf12e662 Copyright (c) 2000-2019 the FFmpeg developers
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] Unknown dref type 0x206c7275 size 12
+
  built with gcc 5.4.0 (CJ 20200411)
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] Processing st: 1, edit list 0 - media time: 2048, duration: 21168000
+
  configuration: --disable-x86asm --enable-librtmp
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] drop a frame at curr_cts: 0 @ 0
+
  libavutil      56. 33.100 / 56. 33.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] drop a frame at curr_cts: 1024 @ 1
+
  libavcodec    58. 55.100 / 58. 55.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] Before avformat_find_stream_info() pos: 385043 bytes read:402457 seeks:0 nb_streams:2
+
  libavformat    58. 30.100 / 58. 30.100
[h264 @ 0x29ab280] nal_unit_type: 7(SPS), nal_ref_idc: 3
+
  libavdevice    58.  9.100 / 58.  9.100
[h264 @ 0x29ab280] nal_unit_type: 8(PPS), nal_ref_idc: 3
+
  libavfilter    7. 58.100 /  7. 58.100
[h264 @ 0x29ab280] nal_unit_type: 6(SEI), nal_ref_idc: 0
+
  libswscale      5.  6.100 / 5.  6.100
[h264 @ 0x29ab280] nal_unit_type: 5(IDR), nal_ref_idc: 3
+
  libswresample  3.  6.100 / 3.  6.100
[h264 @ 0x29ab280] Format yuv420p chosen by get_format().
+
CJ ffmpeg ----
[h264 @ 0x29ab280] Reinit context to 1920x1088, pix_fmt: yuv420p
+
CJ open_input_file(/home/jammy/test.mp4)
[h264 @ 0x29ab280] no picture
+
CJ: before avformat_open_input(/home/jammy/test.mp4)
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] demuxer injecting skip 2048 / discard 0
+
[aac @ 0x29afc80] skip 2048 / discard 0 samples due to side data
+
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] All info found
+
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x29a9800] After avformat_find_stream_info() pos: 450824 bytes read:483220 seeks:0 frames:2
+
 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/jammy/test.mp4':
 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/jammy/test.mp4':
 
   Metadata:
 
   Metadata:
第70行: 第183行:
 
     encoder        : Lavf56.15.102
 
     encoder        : Lavf56.15.102
 
   Duration: 00:08:00.05, start: 0.000000, bitrate: 4817 kb/s
 
   Duration: 00:08:00.05, start: 0.000000, bitrate: 4817 kb/s
     Stream #0:0(und), 1, 1/12800: Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(left), 1920x1080 (1920x1088), 0/1, 4683 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
+
     Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 4683 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
 
     Metadata:
 
     Metadata:
 
       handler_name    : VideoHandler
 
       handler_name    : VideoHandler
     Stream #0:1(und), 1, 1/44100: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
+
     Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
 
     Metadata:
 
     Metadata:
 
       handler_name    : SoundHandler
 
       handler_name    : SoundHandler
Successfully opened the file.
+
CJ open_output_file(rtmp://localhost/myapp/mystream)
Parsing a group of options: output url rtmp://localhost/myapp/mystream.
+
CJ: new_video_stream 0
Applying option c (codec name) with argument copy.
+
CJ: librtmp rtmp_open(rtmp://localhost/myapp/mystream, 2)
Applying option f (force format) with argument flv.
+
CJ ffmpeg: step2
Successfully parsed a group of options.
+
CJ: ffmpeg step3: before transcode()
Opening an output file: rtmp://localhost/myapp/mystream.
+
CJ transcode_init
[rtmp @ 0x2a2e300] No default whitelist set
+
[tcp @ 0x2a2e240] No default whitelist set
+
[tcp @ 0x2a2e240] Original list of addresses:
+
[tcp @ 0x2a2e240] Address 127.0.0.1 port 1935
+
[tcp @ 0x2a2e240] Interleaved list of addresses:
+
[tcp @ 0x2a2e240] Address 127.0.0.1 port 1935
+
[tcp @ 0x2a2e240] Starting connection attempt to 127.0.0.1 port 1935
+
[tcp @ 0x2a2e240] Successfully connected to 127.0.0.1 port 1935
+
[rtmp @ 0x2a2e300] Handshaking...
+
[rtmp @ 0x2a2e300] Type answer 3
+
[rtmp @ 0x2a2e300] Server version 13.14.10.13
+
[rtmp @ 0x2a2e300] Proto = rtmp, path = /myapp/mystream, app = myapp, fname = mystream
+
[rtmp @ 0x2a2e300] Window acknowledgement size = 5000000
+
[rtmp @ 0x2a2e300] Max sent, unacked = 5000000
+
[rtmp @ 0x2a2e300] New incoming chunk size = 4096
+
[rtmp @ 0x2a2e300] Releasing stream...
+
[rtmp @ 0x2a2e300] FCPublish stream...
+
[rtmp @ 0x2a2e300] Creating stream...
+
[rtmp @ 0x2a2e300] Sending publish command for 'mystream'
+
Successfully opened the file.
+
 
Output #0, flv, to 'rtmp://localhost/myapp/mystream':
 
Output #0, flv, to 'rtmp://localhost/myapp/mystream':
 
   Metadata:
 
   Metadata:
第108行: 第201行:
 
     compatible_brands: isomiso2avc1mp41
 
     compatible_brands: isomiso2avc1mp41
 
     encoder        : Lavf58.30.100
 
     encoder        : Lavf58.30.100
     Stream #0:0(und), 0, 1/1000: Video: h264 (High), 1 reference frame ([7][0][0][0] / 0x0007), yuv420p(left), 1920x1080 (0x0), 0/1, q=2-31, 4683 kb/s, 25 fps, 25 tbr, 1k tbn, 12800 tbc (default)
+
     Stream #0:0(und): Video: h264 (High) ([7][0][0][0] / 0x0007), yuv420p, 1920x1080, q=2-31, 4683 kb/s, 25 fps, 25 tbr, 1k tbn, 12800 tbc (default)
 
     Metadata:
 
     Metadata:
 
       handler_name    : VideoHandler
 
       handler_name    : VideoHandler
     Stream #0:1(und), 0, 1/1000: Audio: aac (LC) ([10][0][0][0] / 0x000A), 44100 Hz, stereo, fltp, 128 kb/s (default)
+
     Stream #0:1(und): Audio: aac (LC) ([10][0][0][0] / 0x000A), 44100 Hz, stereo, fltp, 128 kb/s (default)
 
     Metadata:
 
     Metadata:
 
       handler_name    : SoundHandler
 
       handler_name    : SoundHandler
第118行: 第211行:
 
   Stream #0:1 -> #0:1 (copy)
 
   Stream #0:1 -> #0:1 (copy)
 
Press [q] to stop, [?] for help
 
Press [q] to stop, [?] for help
cur_dts is invalid st:0 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
+
frame=  15 fps=0.0 q=-1.0 size=    379kB time=00:00:00.51 bitrate=6079.8kbits/frame=  28 fps= 28 q=-1.0 size=    715kB time=00:00:01.02 bitrate=5735.0kbits/frame=  41 fps= 27 q=-1.0 size=    981kB time=00:00:01.52 bitrate=5285.2kbits/frame=  54 fps= 27 q=-1.0 size=    1280kB time=00:00:02.04 bitrate=5135.7kbits/frame=  66 fps= 26 q=-1.0 size=    1668kB time=00:00:02.53 bitrate=5399.6kbits/frame=  79 fps= 26 q=-1.0 size=    1907kB time=00:00:03.04 bitrate=5136.1kbits/frame=  91 fps= 26 q=-1.0 size=    2163kB time=00:00:03.55 bitrate=4988.2kbits/frame=  104 fps= 26 q=-1.0 size=    2430kB time=00:00:04.04 bitrate=4925.2kbits/[flv @ 0x36c8040] Failed to update header with correct duration.
cur_dts is invalid st:1 (0) [init:1 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
+
[flv @ 0x36c8040] Failed to update header with correct filesize.
    Last message repeated 1 times
+
frame= 112 fps= 26 q=-1.0 Lsize=    2558kB time=00:00:04.36 bitrate=4805.9kbits/s speed=0.998x    
frame=  15 fps=0.0 q=-1.0 size=    379kB time=00:00:00.51 bitrate=6079.8kbits/frame=  28 fps= 28 q=-1.0 size=    715kB time=00:00:01.02 bitrate=5735.0kbits/frame=  41 fps= 27 q=-1.0 size=    981kB time=00:00:01.52 bitrate=5285.2kbits/frame=  54 fps= 27 q=-1.0 size=    1280kB time=00:00:02.04 bitrate=5135.7kbits/frame=  66 fps= 26 q=-1.0 size=    1668kB time=00:00:02.55 bitrate=5351.0kbits/frame=  79 fps= 26 q=-1.0 size=    1907kB time=00:00:03.04 bitrate=5136.1kbits/frame=  91 fps= 26 q=-1.0 size=    2163kB time=00:00:03.55 bitrate=4988.2kbits/[flv @ 0x29ac580] Failed to update header with correct duration.
+
video:2483kB audio:70kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.228437%
[flv @ 0x29ac580] Failed to update header with correct filesize.
+
CJ: ffmpeg step 4: after transcode
frame=   94 fps= 26 q=-1.0 Lsize=    2197kB time=00:00:03.66 bitrate=4904.6kbits/s speed=   1x    
+
CJ: ffmpeg step 5: before exit_program
video:2133kB audio:59kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.228048%
+
 
Input file #0 (/home/jammy/test.mp4):
+
= How to use librtmp in ffmpeg =
  Input stream #0:0 (video): 94 packets read (2183894 bytes);
+
cd ffmpeg root  ( I don't have asm)
  Input stream #0:1 (audio): 161 packets read (60374 bytes);
+
./configure --disable-x86asm --enable-librtmp
  Total: 255 packets (2244268 bytes) demuxed
+
configure exclusive include librtmp or rtmp to config.h
Output file #0 (rtmp://localhost/myapp/mystream):
+
check config.h
  Output stream #0:0 (video): 94 packets muxed (2183894 bytes);
+
<source lang="c">
  Output stream #0:1 (audio): 161 packets muxed (60374 bytes);
+
#define CONFIG_LIBRTMP 1
  Total: 255 packets (2244268 bytes) muxed
+
#define CONFIG_LIBRTMP_PROTOCOL 1
0 frames successfully decoded, 0 decoding errors
+
#define CONFIG_RTMP_PROTOCOL 0
[AVIOContext @ 0x2a2e080] Statistics: 0 seeks, 281 writeouts
+
</source>
[rtmp @ 0x2a2e300] UnPublishing stream...
+
configure create protocol_list.c from PROTOCOL_LIST parsered "URLProtocol" from config.h and libavformat/protocols.c
[rtmp @ 0x2a2e300] Deleting stream...
+
check libavformat/protocol_lists.c, we have &ff_librtmp_protocol added.
[AVIOContext @ 0x29b2580] Statistics: 2630641 bytes read, 0 seeks
+
Exiting normally, received signal 2.
+
make
 +
sudo make install

2020年4月11日 (六) 19:51的最后版本

目录

rtmpdump

source code download:

git clone git://git.ffmpeg.org/rtmpdump

Calling flow:
1. Init

   RTMP_LogSetLevel(level);
   RTMP_LogSetCallback(rtmp_log);
     static void rtmp_log(int level, const char *fmt, va_list args)
   RTMP *r = {};
   RTMP_Init(r); //init RTMP. BufferMS=30000,

filename = " "+ 
app=   
tcUrl= 
pageUrl=
swfUrl=
flashVer=
conn=
live=1
subscribe=
buffer=
swfUrl=
swfVfy=1
  

2. Setup

   RTMP_SetupURL(r, filename)
   RTMP_EnableWrite(r); //r->Link.protocol |= RTMP_FEATURE_WRITE;
   RTMP_Connect(r, NULL)
   RTMP_ConnectStream(r, 0)
   //
   setsockopt()

3. write

   RTMP_Write(r, buf, size);

4. read

   RTMP_Read(r, buf, size);
   RTMP_Pause(r, pause);
   RTMP_SendSeek(r, timestamp);

5. close

  RTMP_Close(r)
  RTMP_Free(RTMP *r) // free(r)

FFMPEG default use

ffmpeg/libavformat/rtmpproto.c

const URLProtocol ff_rtmp[e|s|t|te|ts]_protocol = {     \
    .name           = rtmp[e|s|t|te|ts],                   \
    .url_open2      = rtmp_open,                 \
    .url_read       = rtmp_read,                 \
    .url_read_seek  = rtmp_seek,                 \
    .url_read_pause = rtmp_pause,                \
    .url_write      = rtmp_write,                \
    .url_close      = rtmp_close,                \
    .priv_data_size = sizeof(RTMPContext),       \
    .flags          = URL_PROTOCOL_FLAG_NETWORK, \
    .priv_data_class= &rtmp[e|s|t|te|ts]_class,           \
};
#define RTMP_PROTOCOL(rtmp[e|s|t|te|ts]) 
static const AVClass rtmp[e|s|t|te|ts]##_class = {          \
    .class_name = #rtmp[e|s|t|te|ts],                       \
    .item_name  = av_default_item_name,          \
    .option     = rtmp_options,                  \
    .version    = LIBAVUTIL_VERSION_INT,         \
};  
static const AVOption rtmp_options[] = {
    {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {.i64 = 3000}, 0, INT_MAX, DEC|ENC},
    {"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {.i64 = 10}, 0, INT_MAX, ENC},
    {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {.i64 = -2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
    {"any", "both", 0, AV_OPT_TYPE_CONST, {.i64 = -2}, 0, 0, DEC, "rtmp_live"},
    {"live", "live stream", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, DEC, "rtmp_live"},
    {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, DEC, "rtmp_live"},
    {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
    {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
    {"rtmp_swfhash", "SHA256 hash of the decompressed SWF file (32 bytes).", OFFSET(swfhash), AV_OPT_TYPE_BINARY, .flags = DEC},
    {"rtmp_swfsize", "Size of the decompressed SWF file, required for SWFVerification.", OFFSET(swfsize), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC},
    {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically.", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
    {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
    {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
    {"listen",      "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
    {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1",  OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" },
    { NULL },
};

declared in libformat/protocols.c

extern const URLProtocol ff_rtmp_protocol;
extern const URLProtocol ff_rtmpe_protocol;
extern const URLProtocol ff_rtmps_protocol;
extern const URLProtocol ff_rtmpt_protocol;
extern const URLProtocol ff_rtmpte_protocol;
extern const URLProtocol ff_rtmpts_protocol;

libavformat/protocol_list.c

static const URLProtocol *url_protocols[] = {
    &&ff_rtmp_protocol,
    ....
}

libavformat/makefile

OBJS-$(CONFIG_RTMP_PROTOCOL)  += rtmpproto.o rtmpdigest.o rtmppkt.o
OBJS-$(CONFIG_LIBRTMP_PROTOCOL)          += librtmp.o
OBJS-$(CONFIG_LIBRTMPE_PROTOCOL)         += librtmp.o
OBJS-$(CONFIG_LIBRTMPS_PROTOCOL)         += librtmp.o
OBJS-$(CONFIG_LIBRTMPT_PROTOCOL)         += librtmp.o
OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL)        += librtmp.o
 
SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL)      += rtmpcrypt.o rtmpdigest.o rtmpdh.o
OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL)       += rtmphttp.o

ffmpeg/libavformat/rtmpproto.c

/**
 * Open RTMP connection and verify that the stream can be played.
 *
 * URL syntax: rtmp://server[:port][/app][/playpath][ keyword=value]...
 */
static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **opts)

ffmpeg/config.h

#define CONFI_RTMP_PROTOCOL 1

config.mak

CONFIG_RTMP_PROTOCOL=yes

ffmpeg calling flow

avformat_network_init
ffmpeg_parse_options {//ffmpeg_opt.c
  open_input_file {
    avformat_open_input //utils.c
    choose_decoder(AVCodec->id)
  }
  open_output_file {
    init_output_filter
    av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO)
    avformat_query_codec
    new_video_stream(idx)
  }
}
transcode {
 treancode_init
 init_input_thread
 while(not terminate) {
 }
 free_input_threads
 flush_encoder
 exit
}

Log:
ffmpeg version N-94476-gf12e662 Copyright (c) 2000-2019 the FFmpeg developers

 built with gcc 5.4.0 (CJ 20200411)
 configuration: --disable-x86asm --enable-librtmp
 libavutil      56. 33.100 / 56. 33.100
 libavcodec     58. 55.100 / 58. 55.100
 libavformat    58. 30.100 / 58. 30.100
 libavdevice    58.  9.100 / 58.  9.100
 libavfilter     7. 58.100 /  7. 58.100
 libswscale      5.  6.100 /  5.  6.100
 libswresample   3.  6.100 /  3.  6.100

CJ ffmpeg ----
CJ open_input_file(/home/jammy/test.mp4)
CJ: before avformat_open_input(/home/jammy/test.mp4)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/jammy/test.mp4':

 Metadata:
   major_brand     : isom
   minor_version   : 512
   compatible_brands: isomiso2avc1mp41
   encoder         : Lavf56.15.102
 Duration: 00:08:00.05, start: 0.000000, bitrate: 4817 kb/s
   Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 4683 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
   Metadata:
     handler_name    : VideoHandler
   Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
   Metadata:
     handler_name    : SoundHandler

CJ open_output_file(rtmp://localhost/myapp/mystream)
CJ: new_video_stream 0
CJ: librtmp rtmp_open(rtmp://localhost/myapp/mystream, 2)
CJ ffmpeg: step2
CJ: ffmpeg step3: before transcode()
CJ transcode_init
Output #0, flv, to 'rtmp://localhost/myapp/mystream':

 Metadata:
   major_brand     : isom
   minor_version   : 512
   compatible_brands: isomiso2avc1mp41
   encoder         : Lavf58.30.100
   Stream #0:0(und): Video: h264 (High) ([7][0][0][0] / 0x0007), yuv420p, 1920x1080, q=2-31, 4683 kb/s, 25 fps, 25 tbr, 1k tbn, 12800 tbc (default)
   Metadata:
     handler_name    : VideoHandler
   Stream #0:1(und): Audio: aac (LC) ([10][0][0][0] / 0x000A), 44100 Hz, stereo, fltp, 128 kb/s (default)
   Metadata:
     handler_name    : SoundHandler

Stream mapping:

 Stream #0:0 -> #0:0 (copy)
 Stream #0:1 -> #0:1 (copy)

Press [q] to stop, [?] for help
frame= 15 fps=0.0 q=-1.0 size= 379kB time=00:00:00.51 bitrate=6079.8kbits/frame= 28 fps= 28 q=-1.0 size= 715kB time=00:00:01.02 bitrate=5735.0kbits/frame= 41 fps= 27 q=-1.0 size= 981kB time=00:00:01.52 bitrate=5285.2kbits/frame= 54 fps= 27 q=-1.0 size= 1280kB time=00:00:02.04 bitrate=5135.7kbits/frame= 66 fps= 26 q=-1.0 size= 1668kB time=00:00:02.53 bitrate=5399.6kbits/frame= 79 fps= 26 q=-1.0 size= 1907kB time=00:00:03.04 bitrate=5136.1kbits/frame= 91 fps= 26 q=-1.0 size= 2163kB time=00:00:03.55 bitrate=4988.2kbits/frame= 104 fps= 26 q=-1.0 size= 2430kB time=00:00:04.04 bitrate=4925.2kbits/[flv @ 0x36c8040] Failed to update header with correct duration.
[flv @ 0x36c8040] Failed to update header with correct filesize.
frame= 112 fps= 26 q=-1.0 Lsize= 2558kB time=00:00:04.36 bitrate=4805.9kbits/s speed=0.998x
video:2483kB audio:70kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.228437%
CJ: ffmpeg step 4: after transcode
CJ: ffmpeg step 5: before exit_program

How to use librtmp in ffmpeg

cd ffmpeg root ( I don't have asm)

./configure --disable-x86asm --enable-librtmp

configure exclusive include librtmp or rtmp to config.h
check config.h

#define CONFIG_LIBRTMP 1
#define CONFIG_LIBRTMP_PROTOCOL 1
#define CONFIG_RTMP_PROTOCOL 0

configure create protocol_list.c from PROTOCOL_LIST parsered "URLProtocol" from config.h and libavformat/protocols.c
check libavformat/protocol_lists.c, we have &ff_librtmp_protocol added.

make 
sudo make install