librtmp. Patch by Howard Chu <hyc * highlandsun * com>. Originally committed as revision 22710 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.6
| @@ -66,6 +66,7 @@ version <next>: | |||||
| - VorbisComment writing for FLAC, Ogg FLAC and Ogg Speex files | - VorbisComment writing for FLAC, Ogg FLAC and Ogg Speex files | ||||
| - RTP depacketization of Theora | - RTP depacketization of Theora | ||||
| - HTTP Digest authentication | - HTTP Digest authentication | ||||
| - RTMP/RTMPT/RTMPS/RTMPE/RTMPTE protocol support via librtmp | |||||
| @@ -177,6 +177,7 @@ External library support: | |||||
| --enable-libnut enable NUT (de)muxing via libnut, | --enable-libnut enable NUT (de)muxing via libnut, | ||||
| native (de)muxer exists [no] | native (de)muxer exists [no] | ||||
| --enable-libopenjpeg enable JPEG 2000 decoding via OpenJPEG [no] | --enable-libopenjpeg enable JPEG 2000 decoding via OpenJPEG [no] | ||||
| --enable-librtmp enable RTMP[E] support via librtmp [no] | |||||
| --enable-libschroedinger enable Dirac support via libschroedinger [no] | --enable-libschroedinger enable Dirac support via libschroedinger [no] | ||||
| --enable-libspeex enable Speex decoding via libspeex [no] | --enable-libspeex enable Speex decoding via libspeex [no] | ||||
| --enable-libtheora enable Theora encoding via libtheora [no] | --enable-libtheora enable Theora encoding via libtheora [no] | ||||
| @@ -920,6 +921,7 @@ CONFIG_LIST=" | |||||
| libopencore_amrnb | libopencore_amrnb | ||||
| libopencore_amrwb | libopencore_amrwb | ||||
| libopenjpeg | libopenjpeg | ||||
| librtmp | |||||
| libschroedinger | libschroedinger | ||||
| libspeex | libspeex | ||||
| libtheora | libtheora | ||||
| @@ -2615,6 +2617,7 @@ enabled libnut && require libnut libnut.h nut_demuxer_init -lnut | |||||
| enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb -lm | enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb -lm | ||||
| enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -lm | enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb -lm | ||||
| enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg | enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg | ||||
| enabled librtmp && require librtmp librtmp/rtmp.h RTMP_Init -lrtmp | |||||
| enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) && | enabled libschroedinger && add_cflags $(pkg-config --cflags schroedinger-1.0) && | ||||
| require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0) | require libschroedinger schroedinger/schro.h schro_init $(pkg-config --libs schroedinger-1.0) | ||||
| enabled libspeex && require libspeex speex/speex.h speex_decoder_init -lspeex | enabled libspeex && require libspeex speex/speex.h speex_decoder_init -lspeex | ||||
| @@ -2893,6 +2896,7 @@ echo "libnut enabled ${libnut-no}" | |||||
| echo "libopencore-amrnb support ${libopencore_amrnb-no}" | echo "libopencore-amrnb support ${libopencore_amrnb-no}" | ||||
| echo "libopencore-amrwb support ${libopencore_amrwb-no}" | echo "libopencore-amrwb support ${libopencore_amrwb-no}" | ||||
| echo "libopenjpeg enabled ${libopenjpeg-no}" | echo "libopenjpeg enabled ${libopenjpeg-no}" | ||||
| echo "librtmp enabled ${librtmp-no}" | |||||
| echo "libschroedinger enabled ${libschroedinger-no}" | echo "libschroedinger enabled ${libschroedinger-no}" | ||||
| echo "libspeex enabled ${libspeex-no}" | echo "libspeex enabled ${libspeex-no}" | ||||
| echo "libtheora enabled ${libtheora-no}" | echo "libtheora enabled ${libtheora-no}" | ||||
| @@ -274,7 +274,12 @@ OBJS-$(CONFIG_FILE_PROTOCOL) += file.o | |||||
| OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o | OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o | ||||
| OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o | OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o | ||||
| OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o | OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o | ||||
| OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o | |||||
| # external or internal rtmp | |||||
| RTMP-OBJS-$(CONFIG_LIBRTMP) = librtmp.o | |||||
| RTMP-OBJS-$(!CONFIG_LIBRTMP) = rtmpproto.o rtmppkt.o | |||||
| OBJS-$(CONFIG_RTMP_PROTOCOL) += $(RTMP-OBJS-yes) | |||||
| OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o | OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o | ||||
| OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o | OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o | ||||
| OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o | OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o | ||||
| @@ -218,6 +218,12 @@ void av_register_all(void) | |||||
| REGISTER_PROTOCOL (HTTP, http); | REGISTER_PROTOCOL (HTTP, http); | ||||
| REGISTER_PROTOCOL (PIPE, pipe); | REGISTER_PROTOCOL (PIPE, pipe); | ||||
| REGISTER_PROTOCOL (RTMP, rtmp); | REGISTER_PROTOCOL (RTMP, rtmp); | ||||
| #if CONFIG_LIBRTMP | |||||
| REGISTER_PROTOCOL (RTMP, rtmpt); | |||||
| REGISTER_PROTOCOL (RTMP, rtmpe); | |||||
| REGISTER_PROTOCOL (RTMP, rtmpte); | |||||
| REGISTER_PROTOCOL (RTMP, rtmps); | |||||
| #endif | |||||
| REGISTER_PROTOCOL (RTP, rtp); | REGISTER_PROTOCOL (RTP, rtp); | ||||
| REGISTER_PROTOCOL (TCP, tcp); | REGISTER_PROTOCOL (TCP, tcp); | ||||
| REGISTER_PROTOCOL (UDP, udp); | REGISTER_PROTOCOL (UDP, udp); | ||||
| @@ -22,8 +22,8 @@ | |||||
| #define AVFORMAT_AVFORMAT_H | #define AVFORMAT_AVFORMAT_H | ||||
| #define LIBAVFORMAT_VERSION_MAJOR 52 | #define LIBAVFORMAT_VERSION_MAJOR 52 | ||||
| #define LIBAVFORMAT_VERSION_MINOR 57 | |||||
| #define LIBAVFORMAT_VERSION_MICRO 1 | |||||
| #define LIBAVFORMAT_VERSION_MINOR 58 | |||||
| #define LIBAVFORMAT_VERSION_MICRO 0 | |||||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||
| LIBAVFORMAT_VERSION_MINOR, \ | LIBAVFORMAT_VERSION_MINOR, \ | ||||
| @@ -0,0 +1,206 @@ | |||||
| /* | |||||
| * RTMP network protocol | |||||
| * Copyright (c) 2010 Howard Chu | |||||
| * | |||||
| * This file is part of FFmpeg. | |||||
| * | |||||
| * FFmpeg is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * FFmpeg is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with FFmpeg; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| /** | |||||
| * @file libavformat/librtmp.c | |||||
| * RTMP protocol based on http://rtmpdump.mplayerhq.hu librtmp | |||||
| */ | |||||
| #include "avformat.h" | |||||
| #include <librtmp/rtmp.h> | |||||
| #include <librtmp/log.h> | |||||
| static int rtmp_close(URLContext *s) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| RTMP_Close(r); | |||||
| av_free(r); | |||||
| return 0; | |||||
| } | |||||
| /** | |||||
| * Opens RTMP connection and verifies that the stream can be played. | |||||
| * | |||||
| * URL syntax: rtmp://server[:port][/app][/playpath][ keyword=value]... | |||||
| * where 'app' is first one or two directories in the path | |||||
| * (e.g. /ondemand/, /flash/live/, etc.) | |||||
| * and 'playpath' is a file name (the rest of the path, | |||||
| * may be prefixed with "mp4:") | |||||
| * | |||||
| * Additional RTMP library options may be appended as | |||||
| * space-separated key-value pairs. | |||||
| */ | |||||
| static int rtmp_open(URLContext *s, const char *uri, int flags) | |||||
| { | |||||
| RTMP *r; | |||||
| int rc; | |||||
| r = av_mallocz(sizeof(RTMP)); | |||||
| if (!r) | |||||
| return AVERROR(ENOMEM); | |||||
| switch(av_log_get_level()) { | |||||
| default: | |||||
| case AV_LOG_FATAL: rc = RTMP_LOGCRIT; break; | |||||
| case AV_LOG_ERROR: rc = RTMP_LOGERROR; break; | |||||
| case AV_LOG_WARNING: rc = RTMP_LOGWARNING; break; | |||||
| case AV_LOG_INFO: rc = RTMP_LOGINFO; break; | |||||
| case AV_LOG_VERBOSE: rc = RTMP_LOGDEBUG; break; | |||||
| case AV_LOG_DEBUG: rc = RTMP_LOGDEBUG2; break; | |||||
| } | |||||
| RTMP_LogSetLevel(rc); | |||||
| RTMP_Init(r); | |||||
| if (!RTMP_SetupURL(r, s->filename)) { | |||||
| rc = -1; | |||||
| goto fail; | |||||
| } | |||||
| if (flags & URL_WRONLY) | |||||
| r->Link.protocol |= RTMP_FEATURE_WRITE; | |||||
| if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { | |||||
| rc = -1; | |||||
| goto fail; | |||||
| } | |||||
| s->priv_data = r; | |||||
| s->is_streamed = 1; | |||||
| return 0; | |||||
| fail: | |||||
| av_free(r); | |||||
| return rc; | |||||
| } | |||||
| static int rtmp_write(URLContext *s, uint8_t *buf, int size) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| return RTMP_Write(r, buf, size); | |||||
| } | |||||
| static int rtmp_read(URLContext *s, uint8_t *buf, int size) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| return RTMP_Read(r, buf, size); | |||||
| } | |||||
| static int rtmp_read_pause(URLContext *s, int pause) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| if (pause) | |||||
| r->m_pauseStamp = | |||||
| r->m_channelTimestamp[r->m_mediaChannel]; | |||||
| if (!RTMP_SendPause(r, pause, r->m_pauseStamp)) | |||||
| return -1; | |||||
| return 0; | |||||
| } | |||||
| static int64_t rtmp_read_seek(URLContext *s, int stream_index, | |||||
| int64_t timestamp, int flags) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| if (flags & AVSEEK_FLAG_BYTE) | |||||
| return AVERROR_NOTSUPP; | |||||
| /* seeks are in milliseconds */ | |||||
| timestamp = av_rescale(timestamp, AV_TIME_BASE, 1000); | |||||
| if (!RTMP_SendSeek(r, timestamp)) | |||||
| return -1; | |||||
| return timestamp; | |||||
| } | |||||
| static int rtmp_get_file_handle(URLContext *s) | |||||
| { | |||||
| RTMP *r = s->priv_data; | |||||
| return r->m_sb.sb_socket; | |||||
| } | |||||
| URLProtocol rtmp_protocol = { | |||||
| "rtmp", | |||||
| rtmp_open, | |||||
| rtmp_read, | |||||
| rtmp_write, | |||||
| NULL, /* seek */ | |||||
| rtmp_close, | |||||
| NULL, /* next */ | |||||
| rtmp_read_pause, | |||||
| rtmp_read_seek, | |||||
| rtmp_get_file_handle | |||||
| }; | |||||
| URLProtocol rtmpt_protocol = { | |||||
| "rtmpt", | |||||
| rtmp_open, | |||||
| rtmp_read, | |||||
| rtmp_write, | |||||
| NULL, /* seek */ | |||||
| rtmp_close, | |||||
| NULL, /* next */ | |||||
| rtmp_read_pause, | |||||
| rtmp_read_seek, | |||||
| rtmp_get_file_handle | |||||
| }; | |||||
| URLProtocol rtmpe_protocol = { | |||||
| "rtmpe", | |||||
| rtmp_open, | |||||
| rtmp_read, | |||||
| rtmp_write, | |||||
| NULL, /* seek */ | |||||
| rtmp_close, | |||||
| NULL, /* next */ | |||||
| rtmp_read_pause, | |||||
| rtmp_read_seek, | |||||
| rtmp_get_file_handle | |||||
| }; | |||||
| URLProtocol rtmpte_protocol = { | |||||
| "rtmpte", | |||||
| rtmp_open, | |||||
| rtmp_read, | |||||
| rtmp_write, | |||||
| NULL, /* seek */ | |||||
| rtmp_close, | |||||
| NULL, /* next */ | |||||
| rtmp_read_pause, | |||||
| rtmp_read_seek, | |||||
| rtmp_get_file_handle | |||||
| }; | |||||
| URLProtocol rtmps_protocol = { | |||||
| "rtmps", | |||||
| rtmp_open, | |||||
| rtmp_read, | |||||
| rtmp_write, | |||||
| NULL, /* seek */ | |||||
| rtmp_close, | |||||
| NULL, /* next */ | |||||
| rtmp_read_pause, | |||||
| rtmp_read_seek, | |||||
| rtmp_get_file_handle | |||||
| }; | |||||