FFmpeg  2.1.1
librtmp.c
Go to the documentation of this file.
1 /*
2  * RTMP network protocol
3  * Copyright (c) 2010 Howard Chu
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * RTMP protocol based on http://rtmpdump.mplayerhq.hu/ librtmp
25  */
26 
27 #include "libavutil/avstring.h"
28 #include "libavutil/mathematics.h"
29 #include "libavutil/opt.h"
30 #include "avformat.h"
31 #include "url.h"
32 
33 #include <librtmp/rtmp.h>
34 #include <librtmp/log.h>
35 
36 typedef struct LibRTMPContext {
37  const AVClass *class;
38  RTMP rtmp;
39  char *app;
40  char *playpath;
42 
43 static void rtmp_log(int level, const char *fmt, va_list args)
44 {
45  switch (level) {
46  default:
47  case RTMP_LOGCRIT: level = AV_LOG_FATAL; break;
48  case RTMP_LOGERROR: level = AV_LOG_ERROR; break;
49  case RTMP_LOGWARNING: level = AV_LOG_WARNING; break;
50  case RTMP_LOGINFO: level = AV_LOG_INFO; break;
51  case RTMP_LOGDEBUG: level = AV_LOG_VERBOSE; break;
52  case RTMP_LOGDEBUG2: level = AV_LOG_DEBUG; break;
53  }
54 
55  av_vlog(NULL, level, fmt, args);
56  av_log(NULL, level, "\n");
57 }
58 
59 static int rtmp_close(URLContext *s)
60 {
61  LibRTMPContext *ctx = s->priv_data;
62  RTMP *r = &ctx->rtmp;
63 
64  RTMP_Close(r);
65  return 0;
66 }
67 
68 /**
69  * Open RTMP connection and verify that the stream can be played.
70  *
71  * URL syntax: rtmp://server[:port][/app][/playpath][ keyword=value]...
72  * where 'app' is first one or two directories in the path
73  * (e.g. /ondemand/, /flash/live/, etc.)
74  * and 'playpath' is a file name (the rest of the path,
75  * may be prefixed with "mp4:")
76  *
77  * Additional RTMP library options may be appended as
78  * space-separated key-value pairs.
79  */
80 static int rtmp_open(URLContext *s, const char *uri, int flags)
81 {
82  LibRTMPContext *ctx = s->priv_data;
83  RTMP *r = &ctx->rtmp;
84  int rc = 0, level;
85  char *filename = s->filename;
86 
87  switch (av_log_get_level()) {
88  default:
89  case AV_LOG_FATAL: level = RTMP_LOGCRIT; break;
90  case AV_LOG_ERROR: level = RTMP_LOGERROR; break;
91  case AV_LOG_WARNING: level = RTMP_LOGWARNING; break;
92  case AV_LOG_INFO: level = RTMP_LOGINFO; break;
93  case AV_LOG_VERBOSE: level = RTMP_LOGDEBUG; break;
94  case AV_LOG_DEBUG: level = RTMP_LOGDEBUG2; break;
95  }
96  RTMP_LogSetLevel(level);
97  RTMP_LogSetCallback(rtmp_log);
98 
99  if (ctx->app || ctx->playpath) {
100  int len = strlen(s->filename) + 1;
101  if (ctx->app) len += strlen(ctx->app) + sizeof(" app=");
102  if (ctx->playpath) len += strlen(ctx->playpath) + sizeof(" playpath=");
103 
104  if (!(filename = av_malloc(len)))
105  return AVERROR(ENOMEM);
106 
107  av_strlcpy(filename, s->filename, len);
108  if (ctx->app) {
109  av_strlcat(filename, " app=", len);
110  av_strlcat(filename, ctx->app, len);
111  }
112  if (ctx->playpath) {
113  av_strlcat(filename, " playpath=", len);
114  av_strlcat(filename, ctx->playpath, len);
115  }
116  }
117 
118  RTMP_Init(r);
119  if (!RTMP_SetupURL(r, filename)) {
120  rc = AVERROR_UNKNOWN;
121  goto fail;
122  }
123 
124  if (flags & AVIO_FLAG_WRITE)
125  RTMP_EnableWrite(r);
126 
127  if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) {
128  rc = AVERROR_UNKNOWN;
129  goto fail;
130  }
131 
132  s->is_streamed = 1;
133  rc = 0;
134 fail:
135  if (filename != s->filename)
136  av_freep(&filename);
137  return rc;
138 }
139 
140 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
141 {
142  LibRTMPContext *ctx = s->priv_data;
143  RTMP *r = &ctx->rtmp;
144 
145  return RTMP_Write(r, buf, size);
146 }
147 
148 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
149 {
150  LibRTMPContext *ctx = s->priv_data;
151  RTMP *r = &ctx->rtmp;
152 
153  return RTMP_Read(r, buf, size);
154 }
155 
156 static int rtmp_read_pause(URLContext *s, int pause)
157 {
158  LibRTMPContext *ctx = s->priv_data;
159  RTMP *r = &ctx->rtmp;
160 
161  if (!RTMP_Pause(r, pause))
162  return AVERROR_UNKNOWN;
163  return 0;
164 }
165 
166 static int64_t rtmp_read_seek(URLContext *s, int stream_index,
167  int64_t timestamp, int flags)
168 {
169  LibRTMPContext *ctx = s->priv_data;
170  RTMP *r = &ctx->rtmp;
171 
172  if (flags & AVSEEK_FLAG_BYTE)
173  return AVERROR(ENOSYS);
174 
175  /* seeks are in milliseconds */
176  if (stream_index < 0)
177  timestamp = av_rescale_rnd(timestamp, 1000, AV_TIME_BASE,
179 
180  if (!RTMP_SendSeek(r, timestamp))
181  return AVERROR_UNKNOWN;
182  return timestamp;
183 }
184 
186 {
187  LibRTMPContext *ctx = s->priv_data;
188  RTMP *r = &ctx->rtmp;
189 
190  return RTMP_Socket(r);
191 }
192 
193 #define OFFSET(x) offsetof(LibRTMPContext, x)
194 #define DEC AV_OPT_FLAG_DECODING_PARAM
195 #define ENC AV_OPT_FLAG_ENCODING_PARAM
196 static const AVOption options[] = {
197  {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
198  {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
199  { NULL },
200 };
201 
202 #define RTMP_CLASS(flavor)\
203 static const AVClass lib ## flavor ## _class = {\
204  .class_name = "lib" #flavor " protocol",\
205  .item_name = av_default_item_name,\
206  .option = options,\
207  .version = LIBAVUTIL_VERSION_INT,\
208 };
209 
210 RTMP_CLASS(rtmp)
212  .name = "rtmp",
213  .url_open = rtmp_open,
214  .url_read = rtmp_read,
215  .url_write = rtmp_write,
216  .url_close = rtmp_close,
217  .url_read_pause = rtmp_read_pause,
218  .url_read_seek = rtmp_read_seek,
219  .url_get_file_handle = rtmp_get_file_handle,
220  .priv_data_size = sizeof(LibRTMPContext),
221  .priv_data_class = &librtmp_class,
223 };
224 
225 RTMP_CLASS(rtmpt)
227  .name = "rtmpt",
228  .url_open = rtmp_open,
229  .url_read = rtmp_read,
230  .url_write = rtmp_write,
231  .url_close = rtmp_close,
232  .url_read_pause = rtmp_read_pause,
233  .url_read_seek = rtmp_read_seek,
234  .url_get_file_handle = rtmp_get_file_handle,
235  .priv_data_size = sizeof(LibRTMPContext),
236  .priv_data_class = &librtmpt_class,
238 };
239 
240 RTMP_CLASS(rtmpe)
242  .name = "rtmpe",
243  .url_open = rtmp_open,
244  .url_read = rtmp_read,
245  .url_write = rtmp_write,
246  .url_close = rtmp_close,
247  .url_read_pause = rtmp_read_pause,
248  .url_read_seek = rtmp_read_seek,
249  .url_get_file_handle = rtmp_get_file_handle,
250  .priv_data_size = sizeof(LibRTMPContext),
251  .priv_data_class = &librtmpe_class,
253 };
254 
255 RTMP_CLASS(rtmpte)
257  .name = "rtmpte",
258  .url_open = rtmp_open,
259  .url_read = rtmp_read,
260  .url_write = rtmp_write,
261  .url_close = rtmp_close,
262  .url_read_pause = rtmp_read_pause,
263  .url_read_seek = rtmp_read_seek,
264  .url_get_file_handle = rtmp_get_file_handle,
265  .priv_data_size = sizeof(LibRTMPContext),
266  .priv_data_class = &librtmpte_class,
268 };
269 
270 RTMP_CLASS(rtmps)
272  .name = "rtmps",
273  .url_open = rtmp_open,
274  .url_read = rtmp_read,
275  .url_write = rtmp_write,
276  .url_close = rtmp_close,
277  .url_read_pause = rtmp_read_pause,
278  .url_read_seek = rtmp_read_seek,
279  .url_get_file_handle = rtmp_get_file_handle,
280  .priv_data_size = sizeof(LibRTMPContext),
281  .priv_data_class = &librtmps_class,
283 };
char * app
Definition: librtmp.c:39
const char * s
Definition: avisynth_c.h:668
#define ENC
Definition: librtmp.c:195
int size
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:35
static int64_t rtmp_read_seek(URLContext *s, int stream_index, int64_t timestamp, int flags)
Definition: librtmp.c:166
AVOption.
Definition: opt.h:253
const char * fmt
Definition: avisynth_c.h:669
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const
Rescale a 64-bit integer with specified rounding.
Definition: mathematics.c:60
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: avcodec.h:4153
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
static int rtmp_read_pause(URLContext *s, int pause)
Definition: librtmp.c:156
void av_freep(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:234
uint8_t
Round toward +infinity.
Definition: mathematics.h:71
static int rtmp_close(URLContext *s)
Definition: librtmp.c:59
static int rtmp_open(URLContext *s, const char *uri, int flags)
Open RTMP connection and verify that the stream can be played.
Definition: librtmp.c:80
#define AVSEEK_FLAG_BYTE
seeking based on position in bytes
Definition: avformat.h:1839
#define DEC
Definition: librtmp.c:194
URLProtocol ff_librtmpt_protocol
Definition: librtmp.c:226
#define AV_LOG_VERBOSE
Detailed information.
Definition: avcodec.h:4163
const OptionDef options[]
Definition: ffserver.c:4682
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: avcodec.h:4147
static void rtmp_log(int level, const char *fmt, va_list args)
Definition: librtmp.c:43
#define AVERROR_UNKNOWN
const char * r
Definition: vf_curves.c:103
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: avcodec.h:4168
int av_log_get_level(void)
Get the current log level.
Definition: log.c:288
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:82
goto fail
Definition: avfilter.c:963
URLProtocol ff_librtmpte_protocol
Definition: librtmp.c:256
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avcodec.h:2284
void * av_malloc(size_t size) av_malloc_attrib 1(1)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
URLProtocol ff_librtmpe_protocol
Definition: librtmp.c:241
URLProtocol ff_librtmp_protocol
Definition: librtmp.c:211
#define AV_LOG_INFO
Standard information.
Definition: avcodec.h:4158
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:333
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
Describe the class of an AVClass context structure.
Definition: log.h:50
#define AVSEEK_FLAG_BACKWARD
Definition: avformat.h:1838
void * priv_data
Definition: url.h:44
#define OFFSET(x)
Definition: librtmp.c:193
void void av_vlog(void *avcl, int level, const char *fmt, va_list vl)
Send the specified message to the log if the level is less than or equal to the current av_log_level...
Definition: log.c:281
char * playpath
Definition: librtmp.c:40
static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
Definition: librtmp.c:140
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:92
const char * name
Definition: url.h:55
Round toward -infinity.
Definition: mathematics.h:70
static int flags
Definition: cpu.c:45
uint8_t level
Definition: svq3.c:146
Main libavformat public API header.
char * filename
specified URL
Definition: url.h:45
static int rtmp_get_file_handle(URLContext *s)
Definition: librtmp.c:185
URLProtocol ff_librtmps_protocol
Definition: librtmp.c:271
int len
static int rtmp_read(URLContext *s, uint8_t *buf, int size)
Definition: librtmp.c:148
#define AVERROR(e)
unbuffered private I/O API
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition: avcodec.h:4141
#define RTMP_CLASS(flavor)
Definition: librtmp.c:202