[FFmpeg-soc] [soc]: r4506 - in rtmp: rtmp.patch rtmpdec.c rtmpproto.c
kostya
subversion at mplayerhq.hu
Tue Jun 23 20:18:18 CEST 2009
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,
};
More information about the FFmpeg-soc
mailing list