Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Re: Working genindex for VDR (included)



> 
> Hi,
> 
>       after trying several genindex.c versions mailed on this
> list (and linux-dvb) for getting a index.vdr beeing identical
> with those of VDR, I've written a modified version of genindex.c
> which should be able to scan the mpeg files written by VDR and
> write out an indentical index.vdr.
> 
> I'll need that modified version of genindex.c for burning CDROMs
> with VDR files: every CDROM inludes a 001.vdr, an symbolic link
> resume.vdr pointing to /tmp/resume.vdr, and at least an index.vdr
> matching the 001.vdr.  This should readable for VDR simply by
> mounting such a CDROM at /video/CDROM/ ...
> 
> This version of genindex.c uses an increased BUFFER_SIZE for the
> ringbuffer _and_ an increased buffer size for the stdio interface
> (default is 8k, now its 128*4k).
> 
> 
>        Werner

Hello Werner,
actually, you don't need genindex for your needs. 
Aalthough I apriciate your work, since I was bothered by the same problems
some time ago. But I found a nice solution:
Internally the index.vdr consists of one file per 00x.vdr concatenated to
one large file. I.e. the index start with 0 with every 00x.vdr file. To
reference the correct 00x.vdr file the number (i.e. 00x) is stored in
index.vdr, too.
Therefore, to distribute recordings over many CD-R you only need to split
the existing index.vdr at the file switch boundaries. VDR doesn't mind
starting replay with e.g. 002.vdr as long as index.vdr tells it to do so. I
wrote a litte set of scripts/progs to accomplish this a while ago.
To watch the movies from CD-R one of the scripts restores the files in the
video-dir and creates a link to the 00x.vdr on CD-R (or copies it to HDD).
By concatenating all index.vdr of one movie I am able to recreate the
original index.vdr.
If someone is interested I can post the collection of scripts tomorrow on
this list.

So long,
Christian.



> -------- not an attachment --------------------------------------
> /*
>  * genindex.c	generates index.vdr file from mpeg files written by VDR
>  *
>  * Compile:	gcc -o genindex -O2 -Wall -funroll-loops genindex.c
>  *
>  * Authors:	varies, including me
>  *
>  * Changes:
>  *
>  *   Fri Mar 15, 2002: Move from random scanner to streamid scanner
>  *   for getting the correct offsets of the I-Frames.  Be sure that
>  *   no other multiplex than video ones will be scanned.  
> Increase both
>  *   buffers for ringbuffer and stdio to lower I/O load and increase
>  *   speed.	//werner
>  *
>  * Usage:
>  *
>  *   cd 
> /video[<number>]/<Film>/<Title>/<date>.<time>.<prio>.<life>.rec/
>  *   [mv -f index.vdr index.vdr.bak]
>  *   [pathto/]genindex
>  */
> #include <stdio.h>
> #include <errno.h>
> #include <string.h>
> 
> #define BUFFER_SIZE	4096*128
> 
> #define SC_PICTURE	0x00
> 
> #define NO_PICTURE	0
> #define I_FRAME		1
> #define P_FRAME		2
> #define B_FRAME		3
> 
> #define PROG_STREAM_MAP	0xBC
> #ifndef PRIVATE_STREAM1
> #define PRIVATE_STREAM1	0xBD
> #endif
> #define PADDING_STREAM	0xBE
> #ifndef PRIVATE_STREAM2
> #define PRIVATE_STREAM2	0xBF
> #endif
> #define AUDIO_STREAM_S	0xC0
> #define AUDIO_STREAM_E	0xDF
> #define VIDEO_STREAM_S	0xE0
> #define VIDEO_STREAM_E	0xEF
> #define ECM_STREAM	0xF0
> #define EMM_STREAM	0xF1
> #define DSM_CC_STREAM	0xF2
> #define ISO13522_STREAM	0xF3
> #define PROG_STREAM_DIR	0xFF
> 
> /* VDR supports only offset with sizeof(int) */
> struct tIndex {int offset; unsigned char type; unsigned char 
> number; short reserved; };
> 
> static FILE* fp;
> static FILE* idx;
> static long Foffset;
> static char fname[20];
> static unsigned char fbuffer[BUFFER_SIZE];
> 
> static unsigned char buf(long p)
> {
>     static unsigned char ringbuf[BUFFER_SIZE];
> 
>     if ((p >= Foffset) && (p < (Foffset + BUFFER_SIZE)))
> 	return ringbuf[p-Foffset];
> 
>     Foffset = p;
>     if (fseek(fp, p, SEEK_SET) == 0)
>     {
> 	size_t n = 0;
> 
> 	memset(&ringbuf, 0, sizeof(ringbuf));
> 	n = fread(ringbuf, 1, sizeof(ringbuf), fp);
> 
> 	if ((n < sizeof(ringbuf)) && ferror(fp))
> 	{
> 	    fprintf(stderr, "Could not read from %s: %s\n", 
> fname, strerror(errno));
> 	    exit(1);
> 	}
> 
> 	return ringbuf[p-Foffset];
>     }
>     return 0;
> }
> 
> static int readfile(const unsigned char number)
> { 
>     long filesize;
>     long c = 0;
> 
>     sprintf(fname,"%03d.vdr", number);
>     fp = fopen(fname, "r");
>     if (!fp)
>     {
> 	if (errno != ENOENT)
> 	{
> 	    fprintf(stderr, "Could not open %s: %s\n", fname, 
> strerror(errno));
> 	    return -1;
> 	}
> 	putchar('\n');
> 	return 1;
>     }
>     setbuffer(fp, fbuffer, sizeof(fbuffer));
>     if (fseek(fp, 0, SEEK_END) < 0)
>     {
> 	fprintf(stderr, "Could not goto end of %s: %s\n", 
> fname, strerror(errno));
> 	return -1;
>     }
>     if ((filesize = ftell(fp)) < 0)
>     {
> 	fprintf(stderr, "Could not get size of %s: %s\n", 
> fname, strerror(errno));
> 	return -1;
>     }
> 
>     if (number > 1)
> 	putchar('\n');
>     printf("Reading %s, %ld kB.\n", fname, (filesize >> 10));
>     Foffset = filesize;
> 
>     rewind(fp); /* Even if done for p == 0 in buf() */
> 
>     while (c < filesize)
>     {
> 	if (buf(c) == 0x00 && buf(c+1) == 0x00 && buf(c+2) == 0x01)
> 	{
> 	    const long w = ((buf(c+4) << 8) | buf(c+5)) + 6;	
> /* width of frame */
> 	    const long l = w + c;				
> /* absolute length */
> 
> 	    if (!((l > c) && (l <= filesize)))
> 		break;						
> /* while c < filesize */
> 
> 	    switch (buf(c+3))					
> /* streamid */
> 	    {
> 		case PROG_STREAM_MAP:
> 		case PRIVATE_STREAM2:
> 		case PROG_STREAM_DIR:
> 		case ECM_STREAM     :
> 		case EMM_STREAM     :
> 		case PADDING_STREAM :
> 		case DSM_CC_STREAM  :
> 		case ISO13522_STREAM:
> 		case PRIVATE_STREAM1:
> 		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
> 		    break;
> 		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
> 		    {
> 			long off = (buf(c+8) + 9) + c;		
> /* absolute offset of frame contents */
> 			for (;off < l; off++)
> 			{
> 			    if (buf(off) == 0x00 && buf(off+1) 
> == 0x00 && buf(off+2) == 0x01 &&
> 				buf(off+3) == SC_PICTURE)
> 			    {
> 				const unsigned char Ptype = 
> (buf(off+5)>>3) & 0x07;
> 				if ((Ptype == I_FRAME) || 
> (Ptype == P_FRAME) || (Ptype == B_FRAME))
> 				{
> 				    /* VDR supports only offset 
> with sizeof(int) */
> 				    const struct tIndex i = 
> {(int)c, Ptype, number, 0};
> 
> 				    if (fwrite(&i, 1, 
> sizeof(i), idx) != sizeof(i))
> 				    {
> 					fprintf(stderr, "Error 
> writing index file: %s\n", strerror(errno));
> 					return -1;
> 				    }
> 				    if (Ptype == I_FRAME)
> 				    {
> 					printf("I-Frame found 
> at %ld kB\r", (c >> 10));
> 					fflush(stdout);
> 				    }
> 				    break;			
> /* while off < l */
> 				}				
> /* if Ptype == I_FRAME ... */
> 			    }					
> /* if buf(off) == 0x00 ... */
> 			}					
> /* while off < l */
> 		    }
> 		    break;
> 		default:
> 		    fprintf(stderr, "\nError while scanning 
> file %s, broken mpeg file?\n", fname);
> 		    break;
> 	    }							
> /* switch buf(c+3) */
> 	    c += w;						
> /* Next frame */
> 	}
> 	else							
> /* if buf(c) == 0x00 ... */
> 	    c++;						
> /* Broken file, search for begin */
>     }								
> /* while c < filesize */
>     fclose(fp);
>     return 0;
> }
> 
> int main()
> {
>     int c, ret;
>     if (!(idx = fopen("index.vdr", "w")))
>     {
> 	fprintf(stderr, "Could not open index.vdr: %s\n", 
> strerror(errno));
> 	return -1;
>     }
>     for (c=1; ((ret = readfile(c)) == 0); c++)
> 	__asm__ __volatile__("": : :"memory");
>     fclose(idx);
>     return (ret > 0 ? 0 : 1);
> }
> /* end of genindex.c */
> -----------------------------------------------------------------
> 
> 



Home | Main Index | Thread Index