Update of /cvsroot/xine/xine-lib/src/demuxers
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv3382
Modified Files:
demux_flv.c
Log Message:
Parse script objects and extract stream information.
Index: demux_flv.c
===================================================================
RCS file: /cvsroot/xine/xine-lib/src/demuxers/demux_flv.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- demux_flv.c 14 Dec 2006 18:29:02 -0000 1.10
+++ demux_flv.c 15 Dec 2006 09:39:40 -0000 1.11
@@ -61,7 +61,9 @@
int status;
unsigned char flags;
- unsigned int movie_start;
+ off_t start; /* in bytes */
+ off_t size; /* in bytes */
+ unsigned int length; /* in ms */
unsigned char got_video;
unsigned char got_audio;
@@ -98,6 +100,18 @@
#define FLV_VIDEO_FORMAT_VP6A 0x05 /* On2 VP6 with alphachannel */
#define FLV_VIDEO_FORMAT_SCREEN2 0x06
+#define FLV_DATA_TYPE_NUMBER 0x00
+#define FLV_DATA_TYPE_BOOL 0x01
+#define FLV_DATA_TYPE_STRING 0x02
+#define FLV_DATA_TYPE_OBJECT 0x03
+#define FLC_DATA_TYPE_CLIP 0x04
+#define FLV_DATA_TYPE_REFERENCE 0x07
+#define FLV_DATA_TYPE_ECMARRAY 0x08
+#define FLV_DATA_TYPE_ENDOBJECT 0x09
+#define FLV_DATA_TYPE_ARRAY 0x0a
+#define FLV_DATA_TYPE_DATE 0x0b
+#define FLV_DATA_TYPE_LONGSTRING 0x0c
+
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
@@ -153,8 +167,10 @@
return 0;
}
- this->movie_start = BE_32(&buffer[5]);
- this->input->seek(this->input, this->movie_start, SEEK_SET);
+ this->start = BE_32(&buffer[5]);
+ this->size = this->input->get_length(this->input);
+
+ this->input->seek(this->input, this->start, SEEK_SET);
lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n",
(intmax_t)this->movie_start);
@@ -162,6 +178,114 @@
return 1;
}
+#define BE_F64(buf) ({\
+ union { uint64_t q; double d; } _tmp;\
+ _tmp.q = BE_64(buf);\
+ _tmp.d;\
+})\
+
+static int parse_flv_var(demux_flv_t *this, unsigned char *buf, int size, char
*key) {
+ unsigned char *tmp = buf;
+ unsigned char *end = buf + size;
+ char *str;
+ unsigned char type;
+ int len, num;
+
+ if (size < 1)
+ return 0;
+
+ type = *tmp++;
+
+ switch (type) {
+ case FLV_DATA_TYPE_NUMBER:
+ lprintf(" got number (%f)\n", BE_F64(tmp));
+ if (key) {
+ double val = BE_F64(tmp);
+ if (!strcmp(key, "duration")) {
+ this->length = val * 1000.0;
+ }
+ else if (!strcmp(key, "width")) {
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, val);
+ }
+ else if (!strcmp(key, "height")) {
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, val);
+ }
+ }
+ tmp += 8;
+ break;
+ case FLV_DATA_TYPE_BOOL:
+ lprintf(" got bool (%d)\n", *tmp);
+ tmp++;
+ break;
+ case FLV_DATA_TYPE_STRING:
+ lprintf(" got string (%s)\n", tmp+2);
+ len = BE_16(tmp);
+ tmp += len + 2;
+ break;
+ case FLV_DATA_TYPE_OBJECT:
+ while ((len = BE_16(tmp)) && tmp < end) {
+ lprintf(" got object var (%s)\n", tmp+2);
+ str = tmp + 2;
+ tmp += len + 2;
+ len = parse_flv_var(this, tmp, end-tmp, str);
+ tmp += len;
+ }
+ break;
+ case FLV_DATA_TYPE_ECMARRAY:
+ lprintf(" got EMCA array (%d indices)\n", BE_32(tmp));
+ num = BE_32(tmp);
+ tmp += 4;
+ while (num-- && tmp < end) {
+ lprintf(" got array key (%s)\n", tmp+2);
+ len = BE_16(tmp);
+ str = tmp + 2;
+ tmp += len + 2;
+ len = parse_flv_var(this, tmp, end-tmp, str);
+ tmp += len;
+ }
+ break;
+ case FLV_DATA_TYPE_ARRAY:
+ lprintf(" got array (%d indices)\n", BE_32(tmp));
+ num = BE_32(tmp);
+ tmp += 4;
+ while (num-- && tmp < end) {
+ len = parse_flv_var(this, tmp, end-tmp, NULL);
+ tmp += len;
+ }
+ break;
+ case FLV_DATA_TYPE_DATE:
+ lprintf(" got date (%lld, %d)\n", BE_64(tmp), BE_16(tmp+8));
+ tmp += 10;
+ break;
+ default:
+ lprintf(" got type %d\n", type);
+ break;
+ }
+
+ return (tmp - buf);
+}
+
+static void parse_flv_script(demux_flv_t *this, int size) {
+ unsigned char *buf = xine_xmalloc(size);
+ unsigned char *tmp = buf;
+ unsigned char *end = buf + size;
+ int len;
+
+ if (this->input->read(this->input, buf, size ) != size) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+
+ while (tmp < end) {
+ len = parse_flv_var(this, tmp, end-tmp, NULL);
+ if (len < 1)
+ break;
+ tmp += len;
+ }
+
+ free(buf);
+}
+
static int read_flv_packet(demux_flv_t *this) {
fifo_buffer_t *fifo = NULL;
buf_element_t *buf = NULL;
@@ -240,8 +364,9 @@
buf_type = BUF_VIDEO_FLV1;
break;
case FLV_VIDEO_FORMAT_VP6:
- buf_type = BUF_VIDEO_VP6;
- break;
+ /* FIXME: we need ffmpeg's vp6 codec */
+ /*buf_type = BUF_VIDEO_VP6;
+ break;*/
default:
lprintf(" unsupported video format (%d)...\n", buffer[0] & 0x0F);
buf_type = BUF_VIDEO_UNKNOWN;
@@ -255,13 +380,18 @@
buf = fifo->buffer_pool_alloc(fifo);
buf->decoder_flags =
BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
buf->decoder_info[0] = 7470; /* initial duration */
- buf->size = 0;
+ buf->size = 0; /* no extra data */
buf->type = buf_type;
fifo->put(fifo, buf);
this->got_video = 1;
}
break;
+ case FLV_TAG_TYPE_SCRIPT:
+ lprintf(" got script tag...\n");
+ parse_flv_script(this, remaining_bytes);
+ continue;
+
default:
lprintf(" skipping packet...\n");
this->input->seek(this->input, remaining_bytes, SEEK_CUR);
@@ -276,8 +406,8 @@
buf->extra_info->input_time = pts;
if (this->input->get_length(this->input)) {
- buf->extra_info->input_normpos = (int)(
(double)this->input->get_current_pos(this->input) *
- 65535 /
this->input->get_length(this->input) );
+ buf->extra_info->input_normpos =
+ (int)((double)this->input->get_current_pos(this->input) * 65535.0
/ this->size);
}
if (remaining_bytes > buf->max_size)
@@ -305,44 +435,43 @@
return this->status;
}
-static int seek_flv_file(demux_flv_t *this, int seek_pts) {
+static void seek_flv_file(demux_flv_t *this, int seek_pts) {
unsigned char buffer[16];
- int next_tag = 0;
+ unsigned int pts = this->cur_pts;
+ int len = 0;
+ int next_tag = 0;
int do_rewind = (seek_pts < this->cur_pts);
-
- if (this->cur_pts == seek_pts)
- return this->status;
-
+
+ lprintf(" seeking %s to %d...\n",
+ do_rewind ? "backward" : "forward", seek_pts);
+
if (seek_pts == 0) {
- this->input->seek(this->input, this->movie_start, SEEK_SET);
+ this->input->seek(this->input, this->start, SEEK_SET);
this->cur_pts = 0;
- return this->status;
+ return;
}
-
- lprintf(" seeking %s to %d...\n",
- do_rewind ? "backward" : "forward", seek_pts);
while (do_rewind ? (seek_pts < this->cur_pts) : (seek_pts > this->cur_pts)) {
unsigned char tag_type;
int data_size;
int ptag_size;
- unsigned int pts;
if (next_tag)
this->input->seek(this->input, next_tag, SEEK_CUR);
- if (this->input->read(this->input, buffer, 16) != 16) {
- this->status = DEMUX_FINISHED;
- return this->status;
+ len = this->input->read(this->input, buffer, 16);
+ if (len != 16) {
+ len = (len < 0) ? 0 : len;
+ break;
}
-
+
ptag_size = BE_32(&buffer[0]);
tag_type = buffer[4];
data_size = BE_24(&buffer[5]);
pts = BE_24(&buffer[8]) | (buffer[11] << 24);
if (do_rewind) {
- if (!ptag_size) break;
+ if (!ptag_size) break; /* beginning of movie */
next_tag = -(ptag_size + 16 + 4);
}
else {
@@ -359,11 +488,9 @@
}
/* seek back to the beginning of the tag */
- this->input->seek(this->input, -16, SEEK_CUR);
+ this->input->seek(this->input, -len, SEEK_CUR);
- lprintf( " seeked to %d.\n", this->cur_pts);
-
- return this->status;
+ lprintf( " seeked to %d.\n", pts);
}
@@ -411,11 +538,16 @@
this->status = DEMUX_OK;
if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
- seek_flv_file(this, start_time);
+ if (start_pos && !start_time)
+ start_time = (int64_t) this->length * start_pos / 65535;
+
+ if (!this->length || start_time < this->length) {
+ seek_flv_file(this, start_time);
- if (playing) {
- this->buf_flag_seek = 1;
- _x_demux_flush_engine(this->stream);
+ if (playing) {
+ this->buf_flag_seek = 1;
+ _x_demux_flush_engine(this->stream);
+ }
}
}
@@ -435,9 +567,9 @@
}
static int demux_flv_get_stream_length (demux_plugin_t *this_gen) {
-/* demux_flv_t *this = (demux_flv_t *) this_gen;*/
+ demux_flv_t *this = (demux_flv_t *) this_gen;
- return 0;
+ return this->length;
}
static uint32_t demux_flv_get_capabilities(demux_plugin_t *this_gen) {
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Xine-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xine-cvslog