changeset 3777:026ccd3dc489

added real demuxer
author alex
date Wed, 26 Dec 2001 22:57:51 +0000
parents a90d45d7bde6
children bdc6a07f3bb4
files libmpdemux/Makefile libmpdemux/demux_real.c libmpdemux/demuxer.c libmpdemux/demuxer.h
diffstat 4 files changed, 421 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/Makefile	Wed Dec 26 22:57:22 2001 +0000
+++ b/libmpdemux/Makefile	Wed Dec 26 22:57:51 2001 +0000
@@ -3,7 +3,7 @@
 
 include ../config.mak
 
-SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c frequencies.c demux_fli.c
+SRCS = mp3_hdr.c video.c mpeg_hdr.c cache2.c asfheader.c aviheader.c aviprint.c aviwrite.c demux_asf.c demux_avi.c demux_mov.c demux_mpg.c demux_viv.c demuxer.c dvdauth.c open.c parse_es.c stream.c tv.c tvi_dummy.c tvi_v4l.c frequencies.c demux_fli.c demux_real.c
 ifeq ($(STREAMING),yes)
 SRCS += asf_streaming.c url.c http.c network.c rtp.c
 endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmpdemux/demux_real.c	Wed Dec 26 22:57:51 2001 +0000
@@ -0,0 +1,402 @@
+/*
+    Real parser & demuxer
+    
+    (C) Alex Beregszaszi <alex@naxine.org>
+    
+    Based on FFmpeg's libav/rm.c.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "stream.h"
+#include "demuxer.h"
+#include "stheader.h"
+#include "bswap.h"
+
+#define MKTAG(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
+
+#define MAX_STREAMS 10
+
+typedef struct {
+    int		num_of_packets;
+    int		last_a_stream;
+    int 	a_streams[MAX_STREAMS];
+    int		last_v_stream;
+    int 	v_streams[MAX_STREAMS];
+} real_priv_t;
+
+static void get_str(int isbyte, demuxer_t *demuxer, char *buf, int buf_size)
+{
+    int len, i;
+    char *q;
+    
+    if (isbyte)
+	len = stream_read_char(demuxer->stream);
+    else
+	len = stream_read_word(demuxer->stream);
+#if 1
+    q = buf;
+    for (i = 0; i < len; i++)
+	if (i < (buf_size - 1))
+	    *q++ = stream_read_char(demuxer->stream);
+    *q = 0;
+#else
+    stream_read(demuxer->stream, buf, buf_size);
+#endif
+}
+
+static void skip_str(int isbyte, demuxer_t *demuxer)
+{
+    int len;
+
+    if (isbyte)
+	len = stream_read_char(demuxer->stream);
+    else
+	len = stream_read_word(demuxer->stream);
+
+    stream_skip(demuxer->stream, len);    
+
+    printf("skip_str: %d bytes skipped\n", len);
+}
+
+int real_check_file(demuxer_t* demuxer){
+    real_priv_t *priv;
+    int c;
+
+    mp_msg(MSGT_DEMUX,MSGL_V,"Checking for REAL\n");
+    
+    c = stream_read_dword_le(demuxer->stream);
+    if (c == -256)
+	return 0; /* EOF */
+    if (c != MKTAG('.', 'R', 'M', 'F'))
+	return 0; /* bad magic */
+
+    priv = malloc(sizeof(real_priv_t));
+    memset(priv, 0, sizeof(real_priv_t));
+    demuxer->priv = priv;
+
+    return 1;
+}
+
+// return value:
+//     0 = EOF or no stream found
+//     1 = successfully read a packet
+int demux_real_fill_buffer(demuxer_t *demuxer)
+{
+    real_priv_t *priv = demuxer->priv;
+    demux_stream_t *ds = NULL;
+    int len;
+    int timestamp;
+    int stream_id;
+    int i;
+
+//    printf("num_of_packets: %d\n", priv->num_of_packets);
+
+loop:
+    if (priv->num_of_packets == 0)
+	return 0; /* EOF */
+    stream_skip(demuxer->stream, 2);
+    len = stream_read_word(demuxer->stream);
+    if (len == -256) /* EOF */
+	return 0;
+    if (len < 12)
+    {
+	printf("bad packet len (%d)\n", len);
+	stream_skip(demuxer->stream, len);
+	goto loop;
+//	return 0; /* bad packet */
+    }
+    stream_id = stream_read_word(demuxer->stream);
+    timestamp = stream_read_dword(demuxer->stream);
+
+//    printf("packet: len: %d, stream_id: %d, timestamp: %d\n",
+//	len, stream_id, timestamp);
+    
+    stream_skip(demuxer->stream, 1); /* reserved */
+    stream_skip(demuxer->stream, 1); /* flags */
+
+    priv->num_of_packets--;
+    len -= 12;    
+
+    /* check if stream_id is audio stream */
+    for (i = 0; i < priv->last_a_stream; i++)
+    {
+	if (priv->a_streams[i] == stream_id)
+	{
+//	    printf("packet is audio (id: %d)\n", stream_id);
+	    ds = demuxer->audio; /* FIXME */
+	    break;
+	}
+    }
+    /* check if stream_id is video stream */
+    for (i = 0; i < priv->last_v_stream; i++)
+    {
+	if (priv->v_streams[i] == stream_id)
+	{
+//	    printf("packet is video (id: %d)\n", stream_id);
+	    ds = demuxer->video; /* FIXME */
+	    break;
+	}
+    }
+
+    /* id not found */
+    if (ds == NULL)
+    {
+	printf("unknown stream id (%d)\n", stream_id);
+	stream_skip(demuxer->stream, len);
+	goto loop;	
+    }
+
+    demuxer->filepos = stream_tell(demuxer->stream);
+    ds_read_packet(ds, demuxer->stream, len, timestamp/90000.0f, demuxer->filepos, 0);
+
+    return 1;
+}
+
+void demux_open_real(demuxer_t* demuxer)
+{
+    real_priv_t* priv = demuxer->priv;
+    int num_of_headers;
+    int i;
+
+    stream_skip(demuxer->stream, 4); /* header size */
+    stream_skip(demuxer->stream, 2);
+    stream_skip(demuxer->stream, 4);
+    num_of_headers = stream_read_dword(demuxer->stream);
+//    stream_skip(demuxer->stream, 4); /* number of headers */
+
+    /* parse chunks */
+    for (i = 1; i < num_of_headers; i++)
+    {
+	int chunk, chunk_size;
+	
+	chunk = stream_read_dword_le(demuxer->stream);
+	chunk_size = stream_read_dword(demuxer->stream);
+
+	stream_skip(demuxer->stream, 2);
+	
+	if (chunk_size < 10)
+	    goto fail;
+	
+	printf("Chunk: %.4s (size: %d)\n",
+	    (char *)&chunk, chunk_size);
+	
+	switch(chunk)
+	{
+	    case MKTAG('P', 'R', 'O', 'P'):
+		printf("Properties chunk\n");
+		stream_skip(demuxer->stream, 4); /* max bitrate */
+		stream_skip(demuxer->stream, 4); /* avg bitrate */
+		stream_skip(demuxer->stream, 4); /* max packet size */
+		stream_skip(demuxer->stream, 4); /* avg packet size */
+		stream_skip(demuxer->stream, 4); /* nb packets */
+		stream_skip(demuxer->stream, 4); /* duration */
+		stream_skip(demuxer->stream, 4); /* preroll */
+		stream_skip(demuxer->stream, 4); /* index offset */
+		stream_skip(demuxer->stream, 4); /* data offset */
+		stream_skip(demuxer->stream, 2); /* nb streams */
+		stream_skip(demuxer->stream, 2); /* flags */
+		break;
+	    case MKTAG('C', 'O', 'N', 'T'):
+		printf("Broadcasting informations (title, author, copyright, comment)\n");
+		skip_str(0, demuxer);	/* title */
+		skip_str(0, demuxer);	/* author */
+		skip_str(0, demuxer);	/* copyright */
+		skip_str(0, demuxer);	/* comment */
+		break;
+	    case MKTAG('M', 'D', 'P', 'R'):
+	    {
+		/* new stream */
+		int stream_id;
+		int bitrate;
+		int codec_data_size;
+		int codec_pos;
+		int v;
+
+		stream_id = stream_read_word(demuxer->stream);
+		printf("Found new stream (id: %d)\n", stream_id);
+		
+		stream_skip(demuxer->stream, 4); /* max bitrate */
+		bitrate = stream_read_dword(demuxer->stream); /* bitrate */
+		stream_skip(demuxer->stream, 4); /* max packet size */
+		stream_skip(demuxer->stream, 4); /* avg packet size */
+		stream_skip(demuxer->stream, 4); /* start time */
+		stream_skip(demuxer->stream, 4); /* preroll */
+		stream_skip(demuxer->stream, 4); /* duration */
+		
+		skip_str(1, demuxer);	/* stream description */
+		skip_str(1, demuxer);	/* mimetype */
+		
+		codec_data_size = stream_read_dword(demuxer->stream);
+		codec_pos = stream_tell(demuxer->stream);
+
+		v = stream_read_dword(demuxer->stream);
+		if (v == MKTAG(0xfd, 'a', 'r', '.')) /* audio header */
+		{
+		    sh_audio_t *sh = new_sh_audio(demuxer, stream_id);
+
+		    printf("Found audio stream!\n");
+		    stream_skip(demuxer->stream, 4); /* version */
+		    stream_skip(demuxer->stream, 4); /* .ra4 */
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 2);
+		    stream_skip(demuxer->stream, 4); /* header size */
+		    stream_skip(demuxer->stream, 2); /* add codec info */
+		    stream_skip(demuxer->stream, 4); /* coded frame size */
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 2); /* 1 */
+		    stream_skip(demuxer->stream, 2); /* coded frame size */
+		    stream_skip(demuxer->stream, 4);
+
+		    sh->samplerate = stream_read_word(demuxer->stream);
+		    stream_skip(demuxer->stream, 4);
+		    sh->channels = stream_read_word(demuxer->stream);
+		
+		    {
+			char buf[128];
+			
+			get_str(1, demuxer, buf, sizeof(buf));
+			get_str(1, demuxer, buf, sizeof(buf));
+
+			v = 0; /* not supported audio codec */
+			if (!strcmp(buf, "dnet"))
+			{
+			    printf("Found AC3 audio\n");
+			    sh->format = 0x2000; /* ac3 */
+			    v = 1;
+			}
+		    }
+//		    skip_str(1, demuxer); /* desc */
+//		    skip_str(1, demuxer); /* desc */
+			
+		    /* the audio codec name is stored in desc */
+		    /* available codecs: DNET -> ac3 */
+//		    sh->format = 0x2000; /* ac3 */
+
+		    if (v)
+		    {
+		    printf("Audio codec: 0x%x\n", sh->format);
+		    /* insert as stream */
+		    demuxer->audio->sh = sh;
+		    sh->ds = demuxer->audio;
+		    demuxer->audio->id = stream_id;
+		    
+		    if (priv->last_a_stream+1 < MAX_STREAMS)
+		    {
+			priv->a_streams[priv->last_a_stream] = stream_id;
+			priv->last_a_stream++;
+		    }
+		    }
+		}
+		else
+		{
+		    /* video header */
+		    sh_video_t *sh = new_sh_video(demuxer, stream_id);
+
+		    v = stream_read_dword_le(demuxer->stream);
+		    printf("video: %.4s (%x)\n", (char *)&v, v);
+		    if (v != MKTAG('V', 'I', 'D', 'O'))
+		    {
+			mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported video codec\n");
+			goto skip_this_chunk;
+		    }
+		    
+		    sh->format = stream_read_dword_le(demuxer->stream); /* fourcc */
+		    printf("video fourcc: %.4s (%x)\n", (char *)&sh->format, sh->format);
+
+		    // emulate BITMAPINFOHEADER:
+		    sh->bih = malloc(sizeof(BITMAPINFOHEADER));
+		    memset(sh->bih, 0, sizeof(BITMAPINFOHEADER));
+	    	    sh->bih->biSize = 40;
+		    sh->disp_w = sh->bih->biWidth = stream_read_word(demuxer->stream);
+		    sh->disp_h = sh->bih->biHeight = stream_read_word(demuxer->stream);
+		    sh->bih->biPlanes = 1;
+		    sh->bih->biBitCount = 24;
+		    sh->bih->biCompression = sh->format;
+		    sh->bih->biSizeImage= sh->bih->biWidth*sh->bih->biHeight*3;
+
+		    sh->fps = stream_read_word(demuxer->stream);
+		    sh->frametime = 1.0f/sh->fps;
+		    
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 2);
+		    stream_skip(demuxer->stream, 4);
+		    stream_skip(demuxer->stream, 2);
+
+		    /* h263 hack */
+		    v = stream_read_dword(demuxer->stream);
+		    switch (v)
+		    {
+			case 0x10000000:
+			    /* sub id: 0 */
+			    /* codec id: rv10 */
+			    break;
+			case 0x10003000:
+			case 0x10003001:
+			    /* sub id: 3 */
+			    /* codec id: rv10 */
+			    break;
+			case 0x20001000:
+			    /* codec id: rv20 */
+			    break;
+			default:
+			    /* codec id: none */
+		    }
+		        
+		    /* insert as stream */
+		    demuxer->video->sh = sh;
+		    sh->ds = demuxer->video;
+		    demuxer->video->id = stream_id;
+		    if (priv->last_v_stream+1 < MAX_STREAMS)
+		    {
+			priv->v_streams[priv->last_v_stream] = stream_id;
+			priv->last_v_stream++;
+		    }
+		}
+
+skip_this_chunk:
+		/* skip codec info */
+		v = stream_tell(demuxer->stream) - codec_pos;
+		stream_skip(demuxer->stream, codec_data_size - v);		    
+		break;
+	    }
+	    case MKTAG('D', 'A', 'T', 'A'):
+		goto header_end;
+	    default:
+		printf("Unknown chunk: %x\n", chunk);
+		stream_skip(demuxer->stream, chunk_size - 10);
+		break;
+	}
+    }
+
+header_end:
+    priv->num_of_packets = stream_read_dword(demuxer->stream);
+//    stream_skip(demuxer->stream, 4); /* number of packets */
+    stream_skip(demuxer->stream, 4); /* next data header */
+
+    printf("Packets in file: %d\n", priv->num_of_packets);
+
+    /* disable seeking */
+    demuxer->seekable = 0;
+
+fail:
+    return;
+}
+
+void demux_close_real(demuxer_t *demuxer)
+{
+    real_priv_t* priv = demuxer->priv;
+ 
+    if (priv)
+	free(priv);
+
+    return;
+}
--- a/libmpdemux/demuxer.c	Wed Dec 26 22:57:22 2001 +0000
+++ b/libmpdemux/demuxer.c	Wed Dec 26 22:57:51 2001 +0000
@@ -159,6 +159,7 @@
 int demux_asf_fill_buffer(demuxer_t *demux);
 int demux_mov_fill_buffer(demuxer_t *demux,demux_stream_t* ds);
 int demux_vivo_fill_buffer(demuxer_t *demux);
+int demux_real_fill_buffer(demuxer_t *demux);
 #ifdef USE_TV
 #include "tv.h"
 extern tvi_handle_t *tv_handler;
@@ -181,6 +182,7 @@
     case DEMUXER_TYPE_ASF: return demux_asf_fill_buffer(demux);
     case DEMUXER_TYPE_MOV: return demux_mov_fill_buffer(demux,ds);
     case DEMUXER_TYPE_VIVO: return demux_vivo_fill_buffer(demux);
+    case DEMUXER_TYPE_REAL: return demux_real_fill_buffer(demux);
 #ifdef USE_TV
     case DEMUXER_TYPE_TV: return demux_tv_fill_buffer(demux, tv_handler);
 #endif
@@ -362,6 +364,9 @@
 extern int vivo_check_file(demuxer_t *demuxer);
 extern void demux_open_vivo(demuxer_t *demuxer);
 
+extern int real_check_file(demuxer_t *demuxer);
+extern void demux_open_real(demuxer_t *demuxer);
+
 demuxer_t* demux_open(stream_t *stream,int file_format,int audio_id,int video_id,int dvdsub_id){
 
 //int file_format=(*file_format_ptr);
@@ -425,6 +430,14 @@
       file_format=DEMUXER_TYPE_VIVO;
   }
 }
+//=============== Try to open as REAL file: =================
+if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_REAL){
+  demuxer=new_demuxer(stream,DEMUXER_TYPE_REAL,audio_id,video_id,dvdsub_id);
+  if(real_check_file(demuxer)){
+      mp_msg(MSGT_DEMUXER,MSGL_INFO,"Detected REAL file format!\n");
+      file_format=DEMUXER_TYPE_REAL;
+  }
+}
 //=============== Try to open as FLI file: =================
 if(file_format==DEMUXER_TYPE_UNKNOWN || file_format==DEMUXER_TYPE_FLI){
   demuxer=new_demuxer(stream,DEMUXER_TYPE_FLI,audio_id,video_id,dvdsub_id);
@@ -530,6 +543,10 @@
   demux_open_vivo(demuxer);
   break;
  }
+ case DEMUXER_TYPE_REAL: {
+  demux_open_real(demuxer);
+  break;
+ }
  case DEMUXER_TYPE_ASF: {
   //---- ASF header:
   read_asf_header(demuxer);
--- a/libmpdemux/demuxer.h	Wed Dec 26 22:57:22 2001 +0000
+++ b/libmpdemux/demuxer.h	Wed Dec 26 22:57:51 2001 +0000
@@ -13,6 +13,7 @@
 #define DEMUXER_TYPE_VIVO 8
 #define DEMUXER_TYPE_TV 9
 #define DEMUXER_TYPE_FLI 10
+#define DEMUXER_TYPE_REAL 11
 
 #define DEMUXER_TIME_NONE 0
 #define DEMUXER_TIME_PTS 1