[MPlayer-dev-eng] .TiVo file support

Jeremy Drake mplayer at jdrake.com
Wed Dec 13 07:53:17 CET 2006


On Tue, 12 Dec 2006, Jeremy Drake wrote:

> On Sun, 10 Dec 2006, Nico Sabbi wrote:
>
> > if the output of your processing is a valid mpeg-[pt]s file than writing a
> > linked demuxer is the only sane way to proceed.
> > It's quite easy:
> > in the open() function, after having assigned demuxer->video->id appropriately
> > (depending on your code), add this block
> >
> >
> > {
> >     extern int audio_id, video_id, dvdsub_id;
> >     stream_t* s = new_ds_stream(demuxer->video);
> >     demuxer_t* od = demux_open(s, DEMUXER_TYPE_UNKNOWN,
> >                                audio_id, video_id, dvdsub_id, NULL);
> >     demuxer = new_demuxers_demuxer(od, od, od);
> >   }
> >
> > and in the fill_buffer() function you just have to add the newly
> > created demux_packet() to demuxer->video with
> > ds_add_packet(demuxer->video, dp);
>
> I tried this, and in trying to test it, it would end up calling my demuxer
> again rather than the mpeg one.  I started the program with -demuxer
> mydemuxer option to get it to use my demuxer.  Please help.  I don't know
> what I'm doing ;)

I fixed this by implementing a check_file function.  It now will play a
file!!!

However, I cannot help but feel that my coding sucks.  Since I have a very
weak understanding of how this stuff works, it does some stuff that seems
quite daft.  I would very much appreciate someone taking a look at this
file (trying to attach it) and help me make it nicer.  Such as my tendency
to feed the data to the mpeg demuxer in one-byte packets if they are not
what I am trying to deal with.  I could also use some help with seeking
and knowing where I am in the file, I don't know how to go about that, but
it should be able to work more or less like regular mpeg one at first, and
I can special-case what I need to from there.  Is there some way to make
use of the mpeg seeking code, or do I need to cut, paste, and hack?

Sorry I'm so much trouble, I don't have experience dealing with MPEG,
video players, or anything like that.  All I know is what tivo changed in
the stream, and I got that part working now... ;)

I should warn anyone looking at this that it is not sufficient to build by
itself, it needs the current CVS head of the tivodecode project to link in
via extralibs and extraincs, and also some hacks to some other files
(quick check shows cfg-common.h, libmpdemux/Makefile,
libmpdemux/demuxer.{c,h}



-- 
Injustice anywhere is a threat to justice everywhere.
		-- Martin Luther King, Jr.
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>

#include "config.h"
#include "mp_msg.h"
#include "help_mp.h"
#include "m_option.h"

#include "stream.h"
#include "demuxer.h"
#include "stheader.h"

#include "turing_stream.h"
#include "tivodecoder.h"

int o_verbose = 0;
int o_no_verify = 0;
char * o_mak;

m_option_t demux_tivo_opts[] = {
	{ "mak", &o_mak, CONF_TYPE_STRING,0, 0, 0, NULL },
	{NULL, NULL, 0, 0, 0, 0, NULL}
};

static int mp_stream_read_wrapper (void * mem, int size, void * fh)
{
	return stream_read ((stream_t *)fh, (char *)mem, size);
}

static int mp_packet_add_wrapper (void * mem, int size, void * fh)
{
	demux_packet_t * dp = (demux_packet_t*)fh;
	resize_demux_packet(dp, size);
	memcpy(dp->buffer, mem, size);
	return size;
}

int tivo_check_file(demuxer_t* demuxer)
{
	int id = stream_read_dword_le(demuxer->stream);
	stream_reset(demuxer->stream);
	stream_seek(demuxer->stream, demuxer->movi_start);
	if (id == mmioFOURCC('T', 'i', 'V', 'o'))
	{
		return DEMUXER_TYPE_TIVO;
	}
	return 0;
}

demuxer_t* demux_tivo_open(demuxer_t* demuxer)
{
	turing_state *turing;
	size_t begin_at;
	turing = malloc(sizeof(turing_state));
	memset(turing, 0, sizeof(turing_state));
	demuxer->priv = (void *)turing;
	begin_at = setup_turing_key (turing, demuxer->stream, &mp_stream_read_wrapper, o_mak);
	fprintf(stderr, "begin_at = %lx\n", begin_at);
	stream_seek (demuxer->stream, begin_at);
	if (1)
	{
		extern int audio_id, video_id, dvdsub_id;
		stream_t* s = new_ds_stream(demuxer->video);
		demuxer_t* od = demux_open(s, DEMUXER_TYPE_UNKNOWN,
				audio_id, video_id, dvdsub_id, NULL);
		demuxer = new_demuxers_demuxer(od, od, od);
	}
	return demuxer;
}

int demux_tivo_fill_buffer(demuxer_t* demuxer, demux_stream_t *ds)
{
	off_t pak_start = stream_tell(demuxer->stream);
	unsigned int marker;
	unsigned char byte;
	marker=0xFFFFFFFF;
	while (!demuxer->stream->eof)
	{
		demux_packet_t * dp = new_demux_packet (1);
		dp->pos = pak_start;
		if ((marker & 0xFFFFFF00) == 0x100)
		{
			int ret;
			ret = process_frame(byte, (turing_state *)(demuxer->priv), stream_tell(demuxer->stream), demuxer->stream, &mp_stream_read_wrapper, dp, &mp_packet_add_wrapper);
			if (ret == 1)
			{
				marker = 0xFFFFFFFF;
				ds_add_packet(ds, dp);
				return 1;
			}
			else if (ret == 0)
			{
				mp_packet_add_wrapper(&byte, 1, dp);
				ds_add_packet(ds, dp);
			}
			else if (ret < 0)
			{
				perror ("processing frame");
				return -1;
			}
		}
		else
		{
			mp_packet_add_wrapper(&byte, 1, dp);
			ds_add_packet(ds, dp);
		}
		marker <<= 8;
		if (stream_read(demuxer->stream, &byte, 1) == 0)
		{
			fprintf(stderr, "End of File\n");
			demuxer->stream->eof = 1;
		}
		else
			marker |= byte;
	}
	return 0;
}

demuxer_desc_t demuxer_desc_tivo = {
  "TiVoToGo file demuxer",
  "ttg",
  "TiVoToGo",
  "Jeremy Drake",
  "",
  DEMUXER_TYPE_TIVO,
  1, // safe autodetect
  tivo_check_file,
  demux_tivo_fill_buffer,
  demux_tivo_open,
  NULL,
  NULL,
  NULL
};


More information about the MPlayer-dev-eng mailing list