libavformat/librtmp.c
Go to the documentation of this file.
00001 /*
00002  * RTMP network protocol
00003  * Copyright (c) 2010 Howard Chu
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00027 #include "libavutil/mathematics.h"
00028 #include "avformat.h"
00029 #include "url.h"
00030 
00031 #include <librtmp/rtmp.h>
00032 #include <librtmp/log.h>
00033 
00034 static void rtmp_log(int level, const char *fmt, va_list args)
00035 {
00036     switch (level) {
00037     default:
00038     case RTMP_LOGCRIT:    level = AV_LOG_FATAL;   break;
00039     case RTMP_LOGERROR:   level = AV_LOG_ERROR;   break;
00040     case RTMP_LOGWARNING: level = AV_LOG_WARNING; break;
00041     case RTMP_LOGINFO:    level = AV_LOG_INFO;    break;
00042     case RTMP_LOGDEBUG:   level = AV_LOG_VERBOSE; break;
00043     case RTMP_LOGDEBUG2:  level = AV_LOG_DEBUG;   break;
00044     }
00045 
00046     av_vlog(NULL, level, fmt, args);
00047     av_log(NULL, level, "\n");
00048 }
00049 
00050 static int rtmp_close(URLContext *s)
00051 {
00052     RTMP *r = s->priv_data;
00053 
00054     RTMP_Close(r);
00055     return 0;
00056 }
00057 
00070 static int rtmp_open(URLContext *s, const char *uri, int flags)
00071 {
00072     RTMP *r = s->priv_data;
00073     int rc;
00074 
00075     switch (av_log_get_level()) {
00076     default:
00077     case AV_LOG_FATAL:   rc = RTMP_LOGCRIT;    break;
00078     case AV_LOG_ERROR:   rc = RTMP_LOGERROR;   break;
00079     case AV_LOG_WARNING: rc = RTMP_LOGWARNING; break;
00080     case AV_LOG_INFO:    rc = RTMP_LOGINFO;    break;
00081     case AV_LOG_VERBOSE: rc = RTMP_LOGDEBUG;   break;
00082     case AV_LOG_DEBUG:   rc = RTMP_LOGDEBUG2;  break;
00083     }
00084     RTMP_LogSetLevel(rc);
00085     RTMP_LogSetCallback(rtmp_log);
00086 
00087     RTMP_Init(r);
00088     if (!RTMP_SetupURL(r, s->filename)) {
00089         rc = -1;
00090         goto fail;
00091     }
00092 
00093     if (flags & AVIO_FLAG_WRITE)
00094         RTMP_EnableWrite(r);
00095 
00096     if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) {
00097         rc = -1;
00098         goto fail;
00099     }
00100 
00101     s->is_streamed = 1;
00102     return 0;
00103 fail:
00104     return rc;
00105 }
00106 
00107 static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
00108 {
00109     RTMP *r = s->priv_data;
00110 
00111     return RTMP_Write(r, buf, size);
00112 }
00113 
00114 static int rtmp_read(URLContext *s, uint8_t *buf, int size)
00115 {
00116     RTMP *r = s->priv_data;
00117 
00118     return RTMP_Read(r, buf, size);
00119 }
00120 
00121 static int rtmp_read_pause(URLContext *s, int pause)
00122 {
00123     RTMP *r = s->priv_data;
00124 
00125     if (!RTMP_Pause(r, pause))
00126         return -1;
00127     return 0;
00128 }
00129 
00130 static int64_t rtmp_read_seek(URLContext *s, int stream_index,
00131                               int64_t timestamp, int flags)
00132 {
00133     RTMP *r = s->priv_data;
00134 
00135     if (flags & AVSEEK_FLAG_BYTE)
00136         return AVERROR(ENOSYS);
00137 
00138     /* seeks are in milliseconds */
00139     if (stream_index < 0)
00140         timestamp = av_rescale_rnd(timestamp, 1000, AV_TIME_BASE,
00141             flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
00142 
00143     if (!RTMP_SendSeek(r, timestamp))
00144         return -1;
00145     return timestamp;
00146 }
00147 
00148 static int rtmp_get_file_handle(URLContext *s)
00149 {
00150     RTMP *r = s->priv_data;
00151 
00152     return RTMP_Socket(r);
00153 }
00154 
00155 URLProtocol ff_rtmp_protocol = {
00156     .name                = "rtmp",
00157     .url_open            = rtmp_open,
00158     .url_read            = rtmp_read,
00159     .url_write           = rtmp_write,
00160     .url_close           = rtmp_close,
00161     .url_read_pause      = rtmp_read_pause,
00162     .url_read_seek       = rtmp_read_seek,
00163     .url_get_file_handle = rtmp_get_file_handle,
00164     .priv_data_size      = sizeof(RTMP),
00165     .flags               = URL_PROTOCOL_FLAG_NETWORK,
00166 };
00167 
00168 URLProtocol ff_rtmpt_protocol = {
00169     .name                = "rtmpt",
00170     .url_open            = rtmp_open,
00171     .url_read            = rtmp_read,
00172     .url_write           = rtmp_write,
00173     .url_close           = rtmp_close,
00174     .url_read_pause      = rtmp_read_pause,
00175     .url_read_seek       = rtmp_read_seek,
00176     .url_get_file_handle = rtmp_get_file_handle,
00177     .priv_data_size      = sizeof(RTMP),
00178     .flags               = URL_PROTOCOL_FLAG_NETWORK,
00179 };
00180 
00181 URLProtocol ff_rtmpe_protocol = {
00182     .name                = "rtmpe",
00183     .url_open            = rtmp_open,
00184     .url_read            = rtmp_read,
00185     .url_write           = rtmp_write,
00186     .url_close           = rtmp_close,
00187     .url_read_pause      = rtmp_read_pause,
00188     .url_read_seek       = rtmp_read_seek,
00189     .url_get_file_handle = rtmp_get_file_handle,
00190     .priv_data_size      = sizeof(RTMP),
00191     .flags               = URL_PROTOCOL_FLAG_NETWORK,
00192 };
00193 
00194 URLProtocol ff_rtmpte_protocol = {
00195     .name                = "rtmpte",
00196     .url_open            = rtmp_open,
00197     .url_read            = rtmp_read,
00198     .url_write           = rtmp_write,
00199     .url_close           = rtmp_close,
00200     .url_read_pause      = rtmp_read_pause,
00201     .url_read_seek       = rtmp_read_seek,
00202     .url_get_file_handle = rtmp_get_file_handle,
00203     .priv_data_size      = sizeof(RTMP),
00204     .flags               = URL_PROTOCOL_FLAG_NETWORK,
00205 };
00206 
00207 URLProtocol ff_rtmps_protocol = {
00208     .name                = "rtmps",
00209     .url_open            = rtmp_open,
00210     .url_read            = rtmp_read,
00211     .url_write           = rtmp_write,
00212     .url_close           = rtmp_close,
00213     .url_read_pause      = rtmp_read_pause,
00214     .url_read_seek       = rtmp_read_seek,
00215     .url_get_file_handle = rtmp_get_file_handle,
00216     .priv_data_size      = sizeof(RTMP),
00217     .flags               = URL_PROTOCOL_FLAG_NETWORK,
00218 };