[soc]: r4506 - in rtmp: rtmp.patch rtmpdec.c rtmpproto.c
Author: kostya Date: Tue Jun 23 20:18:17 2009 New Revision: 4506 Log: Convert RTMP demuxer into protocol handler Replaced: rtmp/rtmpproto.c (contents, props changed) - copied, changed from r4505, rtmp/rtmpdec.c Deleted: rtmp/rtmpdec.c Modified: rtmp/rtmp.patch Modified: rtmp/rtmp.patch ============================================================================== --- rtmp/rtmp.patch Tue Jun 23 20:01:44 2009 (r4505) +++ rtmp/rtmp.patch Tue Jun 23 20:18:17 2009 (r4506) @@ -1,192 +1,20 @@ -Index: libavformat/flvdec.c -=================================================================== ---- libavformat/flvdec.c (revision 19214) -+++ libavformat/flvdec.c (working copy) -@@ -304,39 +304,38 @@ - return 0; - } - --static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) -+int ff_flv_read_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *pkt, int *wrong_dts) - { -- FLVContext *flv = s->priv_data; - int ret, i, type, size, flags, is_audio; - int64_t next, pos; - int64_t dts, pts = AV_NOPTS_VALUE; - AVStream *st = NULL; - - for(;;){ -- pos = url_ftell(s->pb); -- url_fskip(s->pb, 4); /* size of previous packet */ -- type = get_byte(s->pb); -- size = get_be24(s->pb); -- dts = get_be24(s->pb); -- dts |= get_byte(s->pb) << 24; -+ pos = url_ftell(pb); -+ url_fskip(pb, 4); /* size of previous packet */ -+ type = get_byte(pb); -+ size = get_be24(pb); -+ dts = get_be24(pb); -+ dts |= get_byte(pb) << 24; - // av_log(s, AV_LOG_DEBUG, "type:%d, size:%d, dts:%d\n", type, size, dts); -- if (url_feof(s->pb)) -+ if (url_feof(pb)) - return AVERROR_EOF; -- url_fskip(s->pb, 3); /* stream id, always 0 */ -+ url_fskip(pb, 3); /* stream id, always 0 */ - flags = 0; - - if(size == 0) - continue; - -- next= size + url_ftell(s->pb); -+ next= size + url_ftell(pb); - - if (type == FLV_TAG_TYPE_AUDIO) { - is_audio=1; -- flags = get_byte(s->pb); -+ flags = get_byte(pb); - size--; - } else if (type == FLV_TAG_TYPE_VIDEO) { - is_audio=0; -- flags = get_byte(s->pb); -+ flags = get_byte(pb); - size--; - if ((flags & 0xf0) == 0x50) /* video info / command frame */ - goto skip; -@@ -346,7 +345,7 @@ - else /* skip packet */ - av_log(s, AV_LOG_DEBUG, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); - skip: -- url_fseek(s->pb, next, SEEK_SET); -+ url_fseek(pb, next, SEEK_SET); - continue; - } - -@@ -370,7 +369,7 @@ - ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && !is_audio)) - || st->discard >= AVDISCARD_ALL - ){ -- url_fseek(s->pb, next, SEEK_SET); -+ url_fseek(pb, next, SEEK_SET); - continue; - } - if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY) -@@ -379,17 +378,17 @@ - } - - // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps -- if(!url_is_streamed(s->pb) && s->duration==AV_NOPTS_VALUE){ -+ if(!url_is_streamed(pb) && s->duration==AV_NOPTS_VALUE){ - int size; -- const int64_t pos= url_ftell(s->pb); -- const int64_t fsize= url_fsize(s->pb); -- url_fseek(s->pb, fsize-4, SEEK_SET); -- size= get_be32(s->pb); -- url_fseek(s->pb, fsize-3-size, SEEK_SET); -- if(size == get_be24(s->pb) + 11){ -- s->duration= get_be24(s->pb) * (int64_t)AV_TIME_BASE / 1000; -+ const int64_t pos= url_ftell(pb); -+ const int64_t fsize= url_fsize(pb); -+ url_fseek(pb, fsize-4, SEEK_SET); -+ size= get_be32(pb); -+ url_fseek(pb, fsize-3-size, SEEK_SET); -+ if(size == get_be24(pb) + 11){ -+ s->duration= get_be24(pb) * (int64_t)AV_TIME_BASE / 1000; - } -- url_fseek(s->pb, pos, SEEK_SET); -+ url_fseek(pb, pos, SEEK_SET); - } - - if(is_audio){ -@@ -407,16 +406,16 @@ - - if (st->codec->codec_id == CODEC_ID_AAC || - st->codec->codec_id == CODEC_ID_H264) { -- int type = get_byte(s->pb); -+ int type = get_byte(pb); - size--; - if (st->codec->codec_id == CODEC_ID_H264) { -- int32_t cts = (get_be24(s->pb)+0xff800000)^0xff800000; // sign extension -+ int32_t cts = (get_be24(pb)+0xff800000)^0xff800000; // sign extension - pts = dts + cts; - if (cts < 0) { // dts are wrong -- flv->wrong_dts = 1; -+ *wrong_dts = 1; - av_log(s, AV_LOG_WARNING, "negative cts, previous timestamps might be wrong\n"); - } -- if (flv->wrong_dts) -+ if (*wrong_dts) - dts = AV_NOPTS_VALUE; - } - if (type == 0) { -@@ -442,7 +441,7 @@ - if (!size) - return AVERROR(EAGAIN); - -- ret= av_get_packet(s->pb, pkt, size); -+ ret= av_get_packet(pb, pkt, size); - if (ret < 0) { - return AVERROR(EIO); - } -@@ -459,6 +458,13 @@ - return ret; - } - -+static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) -+{ -+ FLVContext *flv = s->priv_data; -+ -+ return ff_flv_read_packet(s, &s->pb, pkt, &flv->wrong_dts); -+} -+ - AVInputFormat flv_demuxer = { - "flv", - NULL_IF_CONFIG_SMALL("FLV format"), Index: libavformat/Makefile =================================================================== ---- libavformat/Makefile (revision 19214) +--- libavformat/Makefile (revision 19256) +++ libavformat/Makefile (working copy) -@@ -188,6 +188,7 @@ - OBJS-$(CONFIG_ROQ_DEMUXER) += idroq.o - OBJS-$(CONFIG_ROQ_MUXER) += raw.o - OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o -+OBJS-$(CONFIG_RTMP_DEMUXER) += rtmpdec.o rtmppkt.o - OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ - rtp_aac.o \ - rtp_amr.o \ -@@ -246,6 +247,7 @@ +@@ -246,6 +246,7 @@ OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o -+OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o ++OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmppkt.o OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o -Index: libavformat/flv.h -=================================================================== ---- libavformat/flv.h (revision 19214) -+++ libavformat/flv.h (working copy) -@@ -110,4 +110,6 @@ - AMF_DATA_TYPE_UNSUPPORTED = 0x0d, - } AMFDataType; - -+extern int ff_flv_read_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *pkt, int *wrong_dts); -+ - #endif /* AVFORMAT_FLV_H */ Index: libavformat/allformats.c =================================================================== ---- libavformat/allformats.c (revision 19214) +--- libavformat/allformats.c (revision 19256) +++ libavformat/allformats.c (working copy) -@@ -165,6 +165,7 @@ - REGISTER_MUXDEMUX (RM, rm); - REGISTER_MUXDEMUX (ROQ, roq); - REGISTER_DEMUXER (RPL, rpl); -+ REGISTER_DEMUXER (RTMP, rtmp); - REGISTER_MUXER (RTP, rtp); - REGISTER_DEMUXER (RTSP, rtsp); - REGISTER_DEMUXER (SDP, sdp); -@@ -209,6 +210,7 @@ +@@ -209,6 +209,7 @@ REGISTER_PROTOCOL (GOPHER, gopher); REGISTER_PROTOCOL (HTTP, http); REGISTER_PROTOCOL (PIPE, pipe); Copied and modified: rtmp/rtmpproto.c (from r4505, rtmp/rtmpdec.c) ============================================================================== --- rtmp/rtmpdec.c Tue Jun 23 20:01:44 2009 (r4505, copy source) +++ rtmp/rtmpproto.c Tue Jun 23 20:18:17 2009 (r4506) @@ -1,5 +1,5 @@ /* - * RTMP input format + * RTMP network protocol * Copyright (c) 2009 Kostya Shishkov * * This file is part of FFmpeg. @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + * @file libavformat/rtmpproto.c + * RTMP protocol + */ /* needed for gethostname() */ #define _XOPEN_SOURCE 600 @@ -29,6 +33,7 @@ #include "avformat.h" #include <unistd.h> +#include <stdarg.h> #include <sys/time.h> #include "network.h" @@ -52,7 +57,7 @@ typedef struct RTMPContext { int main_stream_id; uint8_t* flv_data; int flv_size; - ByteIOContext pb; + int flv_off; int wrong_dts; uint32_t video_ts, audio_ts; } RTMPContext; @@ -79,7 +84,7 @@ static const uint8_t rtmp_server_key[] = 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE }; -static void gen_connect(AVFormatContext *s, RTMPContext *rt, const char *proto, +static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto, const char *host, int port, const char *app) { RTMPPacket pkt; @@ -126,13 +131,13 @@ static void gen_connect(AVFormatContext rtmp_packet_write(rt->rtmp_hd, &pkt, rt->chunk_size, rt->prev_pkt[1]); } -static void gen_create_stream(AVFormatContext *s, RTMPContext *rt) +static void gen_create_stream(URLContext *s, RTMPContext *rt) { RTMPPacket pkt; uint8_t *p; double num; - av_log(s, AV_LOG_DEBUG, "Creating stream...\n"); + //av_log(s, AV_LOG_DEBUG, "Creating stream...\n"); rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0, 25); num = 3.0; @@ -145,13 +150,13 @@ static void gen_create_stream(AVFormatCo rtmp_packet_destroy(&pkt); } -static void gen_play(AVFormatContext *s, RTMPContext *rt) +static void gen_play(URLContext *s, RTMPContext *rt) { RTMPPacket pkt; uint8_t *p; double num; - av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath); + //av_log(s, AV_LOG_DEBUG, "Sending play command for '%s'\n", rt->playpath); rtmp_packet_create(&pkt, RTMP_VIDEO_CHANNEL, RTMP_PT_INVOKE, 0, 29 + strlen(rt->playpath)); pkt.extra = rt->main_stream_id; @@ -180,7 +185,7 @@ static void gen_play(AVFormatContext *s, rtmp_packet_destroy(&pkt); } -static void gen_pong(AVFormatContext *s, RTMPContext *rt, RTMPPacket *ppkt) +static void gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt) { RTMPPacket pkt; uint8_t *p; @@ -267,7 +272,7 @@ static int rtmp_validate_digest(uint8_t return 0; } -static int rtmp_handshake(AVFormatContext *s, RTMPContext *rt) +static int rtmp_handshake(URLContext *s, RTMPContext *rt) { AVLFG rnd; uint8_t tosend [RTMP_HANDSHAKE_PACKET_SIZE+1]; @@ -277,7 +282,7 @@ static int rtmp_handshake(AVFormatContex int server_pos, client_pos; uint8_t digest[32]; - av_log(s, AV_LOG_DEBUG, "Handshaking...\n"); + //av_log(s, AV_LOG_DEBUG, "Handshaking...\n"); av_lfg_init(&rnd, 0xDEADC0DE); // generate handshake packet - 1536 bytes of pseudorandom data @@ -295,23 +300,23 @@ static int rtmp_handshake(AVFormatContex url_write(rt->rtmp_hd, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1); i = url_read_complete(rt->rtmp_hd, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1); if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) { - av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); + //av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); return -1; } i = url_read_complete(rt->rtmp_hd, clientdata, RTMP_HANDSHAKE_PACKET_SIZE); if (i != RTMP_HANDSHAKE_PACKET_SIZE) { - av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); + //av_log(s, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); return -1; } - av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n", - serverdata[5], serverdata[6], serverdata[7], serverdata[8]); + //av_log(s, AV_LOG_DEBUG, "Server version %d.%d.%d.%d\n", + // serverdata[5], serverdata[6], serverdata[7], serverdata[8]); server_pos = rtmp_validate_digest(serverdata + 1, 772); if (!server_pos) { server_pos = rtmp_validate_digest(serverdata + 1, 8); if (!server_pos) { - av_log(s, AV_LOG_ERROR, "Server response validating failed\n"); + //av_log(s, AV_LOG_ERROR, "Server response validating failed\n"); return -1; } } @@ -323,7 +328,7 @@ static int rtmp_handshake(AVFormatContex digest, 32, digest); if (memcmp(digest, clientdata + RTMP_HANDSHAKE_PACKET_SIZE - 32, 32)) { - av_log(s, AV_LOG_ERROR, "Signature mismatch\n"); + //av_log(s, AV_LOG_ERROR, "Signature mismatch\n"); return -1; } @@ -341,99 +346,19 @@ static int rtmp_handshake(AVFormatContex return 0; } -static int rtmp_probe(AVProbeData *p) -{ - if (av_strstart(p->filename, "rtmp:", NULL)) - return AVPROBE_SCORE_MAX; - return 0; -} - -static int rtmp_read_header(AVFormatContext *s, - AVFormatParameters *ap) -{ - RTMPContext *rt = s->priv_data; - char proto[8], hostname[256], path[512], app[128], *fname; - int port; - uint8_t buf[2048]; - AVStream *st; - - url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, - path, sizeof(path), s->filename); - - if(port == -1) - port = RTMP_DEFAULT_PORT; - snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port); - url_open(&rt->rtmp_hd, buf, URL_RDWR); - rt->state = STATE_START; - if (rtmp_handshake(s, rt)) - return -1; - - rt->chunk_size = 128; - rt->state = STATE_HANDSHAKED; - //extract "app" part from path - if (!strncmp(path, "/ondemand/", 10)) { - fname = path + 10; - memcpy(app, "ondemand", 9); - } else { - char *p = strchr(path + 1, '/'); - if (!p) { - fname = path + 1; - app[0] = '\0'; - } else { - fname = strchr(p + 1, '/'); - if (!fname) { - fname = p + 1; - memcpy(app, path + 1, p - path - 1); - app[p - path - 1] = 0; - } else { - fname++; - memcpy(app, path + 1, fname - path - 2); - app[fname - path - 2] = 0; - } - } - } - if (!strcmp(fname + strlen(fname) - 4, ".f4v") || - !strcmp(fname + strlen(fname) - 4, ".mp4")) { - memcpy(rt->playpath, "mp4:", 5); - } else { - rt->playpath[0] = ':'; - rt->playpath[0] = 0; - } - strncat(rt->playpath, fname, sizeof(rt->playpath) - 5); - - av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n", - proto, path, app, rt->playpath); - gen_connect(s, rt, proto, hostname, port, app); - - st = av_new_stream(s, 0); - if (!st) - return -1; - st->codec->codec_type = CODEC_TYPE_VIDEO; - av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ - - st = av_new_stream(s, 1); - if (!st) - return -1; - st->codec->codec_type = CODEC_TYPE_AUDIO; - av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ - - init_put_byte(&rt->pb, NULL, 0, 0, NULL, NULL, NULL, NULL); - return 0; -} - -static int rtmp_parse_result(AVFormatContext *s, RTMPContext *rt, RTMPPacket *pkt) +static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt) { int i, t; switch (pkt->type) { case RTMP_PT_CHUNK_SIZE: if (pkt->data_size != 4) { - av_log(s, AV_LOG_ERROR, "Chunk size change packet is not 4 (%d)\n", - pkt->data_size); + //av_log(s, AV_LOG_ERROR, "Chunk size change packet is not 4 (%d)\n", + // pkt->data_size); return -1; } rt->chunk_size = AV_RB32(pkt->data); - av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size); + //av_log(s, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size); break; case RTMP_PT_PING: t = AV_RB16(pkt->data); @@ -453,7 +378,7 @@ static int rtmp_parse_result(AVFormatCon case STATE_CONNECTING: //extract a number from result if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) - av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n"); + av_log(NULL, AV_LOG_WARNING, "Unexpected reply on connect()\n"); else rt->main_stream_id = (int) av_int2dbl(AV_RB64(pkt->data + 21)); gen_play(s, rt); @@ -469,7 +394,7 @@ static int rtmp_parse_result(AVFormatCon return 0; } -static int rtmp_read_packet(AVFormatContext *s, AVPacket *pkt) +static int get_packet(URLContext *s) { RTMPContext *rt = s->priv_data; struct timespec ts; @@ -478,7 +403,7 @@ static int rtmp_read_packet(AVFormatCont ts.tv_sec = 0; ts.tv_nsec = 500000000; - while (url_ftell(&rt->pb) == rt->flv_size) { + for(;;) { RTMPPacket rpkt; int has_data = 0; if ((ret = rtmp_packet_read(rt->rtmp_hd, &rpkt, @@ -512,50 +437,168 @@ static int rtmp_read_packet(AVFormatCont rt->audio_ts += rpkt.timestamp; ts = rt->audio_ts; } + rt->flv_off = 0; rt->flv_size = rpkt.data_size + 15; rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size); - bytestream_put_be32(&p, 0); bytestream_put_byte(&p, rpkt.type); bytestream_put_be24(&p, rpkt.data_size); bytestream_put_be24(&p, ts); bytestream_put_byte(&p, ts >> 24); bytestream_put_be24(&p, 0); bytestream_put_buffer(&p, rpkt.data, rpkt.data_size); + bytestream_put_be32(&p, 0); has_data = 1; } else if (rpkt.type == RTMP_PT_METADATA) { - rt->flv_size = rpkt.data_size + 4; + rt->flv_off = 0; + rt->flv_size = rpkt.data_size; rt->flv_data = av_realloc(rt->flv_data, rt->flv_size); - memset(rt->flv_data, 0, 4); //previous packet size - memcpy(rt->flv_data + 4, rpkt.data, rpkt.data_size); + memcpy(rt->flv_data, rpkt.data, rpkt.data_size); has_data = 1; } rtmp_packet_destroy(&rpkt); - if (has_data) { - init_put_byte(&rt->pb, rt->flv_data, rt->flv_size, 0, NULL, NULL, NULL, NULL); + if (has_data) break; + } + return 0; +} + +/** + * url syntax: rtp://host:port[?option=val...] + * option: 'ttl=n' : set the ttl value (for multicast only) + * 'localport=n' : set the local port to n + */ +static int rtmp_open(URLContext *s, const char *uri, int flags) +{ + RTMPContext *rt; + char proto[8], hostname[256], path[1024], app[128], *fname; + uint8_t buf[2048]; + int port, is_input; + + is_input = !(flags & URL_WRONLY); + + rt = av_mallocz(sizeof(RTMPContext)); + if (!rt) + return AVERROR(ENOMEM); + s->priv_data = rt; + + url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, + path, sizeof(path), s->filename); + + if (port == -1) + port = RTMP_DEFAULT_PORT; + snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port); + + if (url_open(&rt->rtmp_hd, buf, URL_RDWR) < 0) + goto fail; + + if (!is_input) { + //av_log(s, AV_LOG_ERROR, "RTMP output is not supported yet\n"); + goto fail; + } else { + rt->state = STATE_START; + if (rtmp_handshake(s, rt)) + return -1; + + rt->chunk_size = 128; + rt->state = STATE_HANDSHAKED; + //extract "app" part from path + if (!strncmp(path, "/ondemand/", 10)) { + fname = path + 10; + memcpy(app, "ondemand", 9); + } else { + char *p = strchr(path + 1, '/'); + if (!p) { + fname = path + 1; + app[0] = '\0'; + } else { + fname = strchr(p + 1, '/'); + if (!fname) { + fname = p + 1; + strncpy(app, path + 1, p - path - 1); + app[p - path - 1] = '\0'; + } else { + fname++; + strncpy(app, path + 1, fname - path - 2); + app[fname - path - 2] = '\0'; + } } } - ret = ff_flv_read_packet(s, &rt->pb, pkt, &rt->wrong_dts); - if (ret == AVERROR_EOF) - return AVERROR(EAGAIN); - return ret; + if (!strcmp(fname + strlen(fname) - 4, ".f4v") || + !strcmp(fname + strlen(fname) - 4, ".mp4")) { + memcpy(rt->playpath, "mp4:", 5); + } else { + rt->playpath[0] = ':'; + rt->playpath[0] = 0; + } + strncat(rt->playpath, fname, sizeof(rt->playpath) - 5); + + //av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n", + // proto, path, app, rt->playpath); + gen_connect(s, rt, proto, hostname, port, app); + } + + rt->flv_data = av_malloc(13); + rt->flv_size = 13; + rt->flv_off = 0; + memcpy(rt->flv_data, "FLV\1\5\0\0\0\011\0\0\0\0", 13); + + s->max_packet_size = url_get_max_packet_size(rt->rtmp_hd); + s->is_streamed = 1; + return 0; + +fail: + if (rt->rtmp_hd) + url_close(rt->rtmp_hd); + av_free(rt); + return AVERROR(EIO); } -static int rtmp_read_close(AVFormatContext *s) +static int rtmp_read(URLContext *s, uint8_t *buf, int size) { RTMPContext *rt = s->priv_data; + int orig_size = size; + int ret; + + while (size > 0) { + int data_left = rt->flv_size - rt->flv_off; + + if (data_left >= size) { + memcpy(buf, rt->flv_data + rt->flv_off, size); + rt->flv_off += size; + return orig_size; + } + if (data_left > 0) { + memcpy(buf, rt->flv_data + rt->flv_off, data_left); + buf += data_left; + size -= data_left; + rt->flv_off = rt->flv_size; + } + if ((ret = get_packet(s)) < 0) + return ret; + } + return orig_size; +} + +static int rtmp_write(URLContext *h, uint8_t *buf, int size) +{ + return 0; +} + +static int rtmp_close(URLContext *h) +{ + RTMPContext *rt = h->priv_data; av_freep(&rt->flv_data); url_close(rt->rtmp_hd); + av_free(rt); return 0; } -AVInputFormat rtmp_demuxer = { +URLProtocol rtmp_protocol = { "rtmp", - NULL_IF_CONFIG_SMALL("RTMP"), - sizeof(RTMPContext), - rtmp_probe, - rtmp_read_header, - rtmp_read_packet, - rtmp_read_close, + rtmp_open, + rtmp_read, + rtmp_write, + NULL, /* seek */ + rtmp_close, };
Hi, On Tue, Jun 23, 2009 at 2:18 PM, kostya <subversion@mplayerhq.hu> wrote:
Convert RTMP demuxer into protocol handler
Might be a good moment to discuss how we'd like to do seeking in these cases - same goes for MMS at some level as well (it's ASF, but seeking is suddenly done at protocol level). Btw great work so far Kostya, I'll try to do some review tonight. Ronald
On Tue, Jun 23, 2009 at 02:23:44PM -0400, Ronald S. Bultje wrote:
Hi,
On Tue, Jun 23, 2009 at 2:18 PM, kostya <subversion@mplayerhq.hu> wrote:
Convert RTMP demuxer into protocol handler
Might be a good moment to discuss how we'd like to do seeking in these cases - same goes for MMS at some level as well (it's ASF, but seeking is suddenly done at protocol level).
The easiest solution to me is to introduce int url_seek_protocol_specific(int64_t timestamp) to URLProtocol. It will allow sending generic seek commands to server in case of streamed media by means of protocol handler. As a side effect I'll have an opportunity to bump LIBAVFORMAT_VERSION_MAJOR and to use av_log() with URLContext :)
Btw great work so far Kostya, I'll try to do some review tonight.
I promised to deliver more or less working client before LinuxTag, so I'm trying. Writing streaming part would be a bit harder.
Ronald
Hi, On Tue, Jun 23, 2009 at 2:46 PM, Kostya <kostya.shishkov@gmail.com> wrote:
The easiest solution to me is to introduce int url_seek_protocol_specific(int64_t timestamp)
Or just introduce a new whence, just like we did for getting the length? Then keep using url_seek(). I was being more design, like maybe you'd want to expose a new demuxer or so which handles "asf-in-mms" or so, but I guess that kinda sucks also. Ronald
participants (3)
-
kostya -
Kostya -
Ronald S. Bultje