Libav 0.7.1
|
00001 /* 00002 * RTMP network protocol 00003 * Copyright (c) 2010 Howard Chu 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "avformat.h" 00028 #include "url.h" 00029 00030 #include <librtmp/rtmp.h> 00031 #include <librtmp/log.h> 00032 00033 static void rtmp_log(int level, const char *fmt, va_list args) 00034 { 00035 switch (level) { 00036 default: 00037 case RTMP_LOGCRIT: level = AV_LOG_FATAL; break; 00038 case RTMP_LOGERROR: level = AV_LOG_ERROR; break; 00039 case RTMP_LOGWARNING: level = AV_LOG_WARNING; break; 00040 case RTMP_LOGINFO: level = AV_LOG_INFO; break; 00041 case RTMP_LOGDEBUG: level = AV_LOG_VERBOSE; break; 00042 case RTMP_LOGDEBUG2: level = AV_LOG_DEBUG; break; 00043 } 00044 00045 av_vlog(NULL, level, fmt, args); 00046 av_log(NULL, level, "\n"); 00047 } 00048 00049 static int rtmp_close(URLContext *s) 00050 { 00051 RTMP *r = s->priv_data; 00052 00053 RTMP_Close(r); 00054 av_free(r); 00055 return 0; 00056 } 00057 00070 static int rtmp_open(URLContext *s, const char *uri, int flags) 00071 { 00072 RTMP *r; 00073 int rc; 00074 00075 r = av_mallocz(sizeof(RTMP)); 00076 if (!r) 00077 return AVERROR(ENOMEM); 00078 00079 switch (av_log_get_level()) { 00080 default: 00081 case AV_LOG_FATAL: rc = RTMP_LOGCRIT; break; 00082 case AV_LOG_ERROR: rc = RTMP_LOGERROR; break; 00083 case AV_LOG_WARNING: rc = RTMP_LOGWARNING; break; 00084 case AV_LOG_INFO: rc = RTMP_LOGINFO; break; 00085 case AV_LOG_VERBOSE: rc = RTMP_LOGDEBUG; break; 00086 case AV_LOG_DEBUG: rc = RTMP_LOGDEBUG2; break; 00087 } 00088 RTMP_LogSetLevel(rc); 00089 RTMP_LogSetCallback(rtmp_log); 00090 00091 RTMP_Init(r); 00092 if (!RTMP_SetupURL(r, s->filename)) { 00093 rc = -1; 00094 goto fail; 00095 } 00096 00097 if (flags & AVIO_FLAG_WRITE) 00098 RTMP_EnableWrite(r); 00099 00100 if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { 00101 rc = -1; 00102 goto fail; 00103 } 00104 00105 s->priv_data = r; 00106 s->is_streamed = 1; 00107 return 0; 00108 fail: 00109 av_free(r); 00110 return rc; 00111 } 00112 00113 static int rtmp_write(URLContext *s, const uint8_t *buf, int size) 00114 { 00115 RTMP *r = s->priv_data; 00116 00117 return RTMP_Write(r, buf, size); 00118 } 00119 00120 static int rtmp_read(URLContext *s, uint8_t *buf, int size) 00121 { 00122 RTMP *r = s->priv_data; 00123 00124 return RTMP_Read(r, buf, size); 00125 } 00126 00127 static int rtmp_read_pause(URLContext *s, int pause) 00128 { 00129 RTMP *r = s->priv_data; 00130 00131 if (!RTMP_Pause(r, pause)) 00132 return -1; 00133 return 0; 00134 } 00135 00136 static int64_t rtmp_read_seek(URLContext *s, int stream_index, 00137 int64_t timestamp, int flags) 00138 { 00139 RTMP *r = s->priv_data; 00140 00141 if (flags & AVSEEK_FLAG_BYTE) 00142 return AVERROR(ENOSYS); 00143 00144 /* seeks are in milliseconds */ 00145 if (stream_index < 0) 00146 timestamp = av_rescale_rnd(timestamp, 1000, AV_TIME_BASE, 00147 flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); 00148 00149 if (!RTMP_SendSeek(r, timestamp)) 00150 return -1; 00151 return timestamp; 00152 } 00153 00154 static int rtmp_get_file_handle(URLContext *s) 00155 { 00156 RTMP *r = s->priv_data; 00157 00158 return RTMP_Socket(r); 00159 } 00160 00161 URLProtocol ff_rtmp_protocol = { 00162 .name = "rtmp", 00163 .url_open = rtmp_open, 00164 .url_read = rtmp_read, 00165 .url_write = rtmp_write, 00166 .url_close = rtmp_close, 00167 .url_read_pause = rtmp_read_pause, 00168 .url_read_seek = rtmp_read_seek, 00169 .url_get_file_handle = rtmp_get_file_handle 00170 }; 00171 00172 URLProtocol ff_rtmpt_protocol = { 00173 .name = "rtmpt", 00174 .url_open = rtmp_open, 00175 .url_read = rtmp_read, 00176 .url_write = rtmp_write, 00177 .url_close = rtmp_close, 00178 .url_read_pause = rtmp_read_pause, 00179 .url_read_seek = rtmp_read_seek, 00180 .url_get_file_handle = rtmp_get_file_handle 00181 }; 00182 00183 URLProtocol ff_rtmpe_protocol = { 00184 .name = "rtmpe", 00185 .url_open = rtmp_open, 00186 .url_read = rtmp_read, 00187 .url_write = rtmp_write, 00188 .url_close = rtmp_close, 00189 .url_read_pause = rtmp_read_pause, 00190 .url_read_seek = rtmp_read_seek, 00191 .url_get_file_handle = rtmp_get_file_handle 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 }; 00204 00205 URLProtocol ff_rtmps_protocol = { 00206 .name = "rtmps", 00207 .url_open = rtmp_open, 00208 .url_read = rtmp_read, 00209 .url_write = rtmp_write, 00210 .url_close = rtmp_close, 00211 .url_read_pause = rtmp_read_pause, 00212 .url_read_seek = rtmp_read_seek, 00213 .url_get_file_handle = rtmp_get_file_handle 00214 };