Index: stream/stream.c =================================================================== --- stream/stream.c (revision 31339) +++ stream/stream.c (working copy) @@ -70,6 +70,7 @@ extern const stream_info_t stream_info_smb; extern const stream_info_t stream_info_sdp; extern const stream_info_t stream_info_rtsp_sip; +extern const stream_info_t stream_info_rtmp; extern const stream_info_t stream_info_cue; extern const stream_info_t stream_info_null; @@ -99,7 +100,10 @@ &stream_info_rtp, &stream_info_udp, &stream_info_http2, +#ifdef CONFIG_LIBRTMP + &stream_info_rtmp, #endif +#endif #ifdef CONFIG_DVBIN &stream_info_dvb, #endif Index: stream/stream_rtmp.c =================================================================== --- stream/stream_rtmp.c (revision 0) +++ stream/stream_rtmp.c (revision 0) @@ -0,0 +1,169 @@ +/* + * stream layer for RTMP, based on RTMPDump librtmp. + * + * Copyright (C) 2010 Howard Chu + * + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include + +#include "stream.h" +#include "m_option.h" +#include "m_struct.h" +#include "libmpdemux/demuxer.h" +#include + +static int +rtmp_stream_write(stream_t *s, char *buffer, int size) +{ + RTMP *r = s->priv; + return RTMP_Write(r, buffer, size); +} + +static int +rtmp_stream_read(int fd, char *buffer, int size, + streaming_ctrl_t *streaming_ctrl) +{ + RTMP *r = streaming_ctrl->data; + (void)fd; + return RTMP_Read(r, buffer, size); +} + +static int rtmp_stream_ctrl(stream_t *s, int cmd, void *arg) +{ + RTMP *r = s->priv; + switch (cmd) { + case STREAM_CTRL_GET_TIME_LENGTH: + *(double *) arg = RTMP_GetDuration(r); + return STREAM_OK; + case STREAM_CTRL_GET_CURRENT_TIME: + *(double *) arg = r->m_mediaStamp / 1000.0; + return STREAM_OK; + case STREAM_CTRL_SEEK_TO_TIME: { + int byterate = s->pos / r->m_mediaStamp; + int newpos = *(double *)arg * 1000; + RTMP_SendSeek(r, newpos); + s->pos = byterate * newpos; + } + return STREAM_OK; + } + return STREAM_UNSUPPORTED; +} + +static int rtmp_stream_seek(stream_t *s, off_t pos) +{ + RTMP *r = s->priv; + if (pos == 0) { + RTMP_SendSeek(r, 0); + return 1; + } + return 0; +} + +static void rtmp_stream_close(stream_t *s) +{ + RTMP *r = s->priv; + + s->streaming_ctrl->data = NULL; + streaming_ctrl_free(s->streaming_ctrl); + s->streaming_ctrl = NULL; + + RTMP_Close(r); + RTMP_Free(r); +} + +static int +rtmp_stream_open(stream_t *stream, int mode, void *opts, int *file_format) +{ + RTMP *r = NULL; + int rc; + extern int network_bandwidth; + + (void) opts; + + mp_msg(MSGT_OPEN, MSGL_INFO, "STREAM_RTMP, URL: %s\n", stream->url); + + stream->streaming_ctrl = streaming_ctrl_new(); + if (!stream->streaming_ctrl) + return STREAM_ERROR; + stream->streaming_ctrl->bandwidth = network_bandwidth; + + r = RTMP_Alloc(); + if (!r) { + rc = STREAM_ERROR; + goto fail; + } + + RTMP_Init(r); + + if (!RTMP_SetupURL(r, stream->url)) + { + rc = STREAM_UNSUPPORTED; + goto fail; + } + + if (mode == STREAM_WRITE) + RTMP_EnableWrite(r); + + if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0)) { + mp_msg(MSGT_NETWORK, MSGL_ERR, "RTMP_Connect failed\n"); + rc = STREAM_ERROR; + goto fail; + } + + stream->streaming_ctrl->data = r; + stream->streaming_ctrl->streaming_read = rtmp_stream_read; + stream->streaming_ctrl->streaming_seek = NULL; + stream->streaming_ctrl->prebuffer_size = 128 * 1024; + stream->streaming_ctrl->buffering = 1; + stream->streaming_ctrl->status = streaming_playing_e; + + stream->seek = rtmp_stream_seek; + stream->control = rtmp_stream_ctrl; + stream->close = rtmp_stream_close; + stream->write_buffer = rtmp_stream_write; + stream->fd = r->m_sb.sb_socket; + stream->type = STREAMTYPE_STREAM; + stream->priv = r; + + *file_format = DEMUXER_TYPE_LAVF_PREFERRED; + fixup_network_stream_cache(stream); + + return STREAM_OK; + + fail: + RTMP_Close(r); + RTMP_Free(r); + streaming_ctrl_free(stream->streaming_ctrl); + stream->streaming_ctrl = NULL; + return rc; +} + +const stream_info_t stream_info_rtmp = { + "FLV over RTMP streaming", + "rtmp", + "Howard Chu", + "native rtmp support", + rtmp_stream_open, + {"rtmp", "rtmpt", "rtmpe", "rtmpte", "rtmps", "rtmpts", NULL}, + NULL, + 0 /* Urls are complicated */ +};