Video Player for independant game / libtheora port first try

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
patbier
DC Developer
DC Developer
Posts: 152
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Video Player for independant game / libtheora port first try

Post by patbier »

Hello,

I'm looking for a video player to use for the intro video for my game in developpement (Dynamite Dreams).
I know that there was a huge work for vcdc (libmpeg2) and recently for xvid.
But I'm not sure it could be used in an independant game without releasing source code (gpl)
So I'm looking for a open and free video codec I can port / use on Dreamcast.

My first try is libtheora, which is fully open and free.

I achieved in compiling it for KOS, here is how to :

- I consider you have a working kos toolchain

- last version of libtheora needs last version of libogg and libvorbis.
So, you have to update the vorbis libraries in kos-ports
Download the last versions : http://www.xiph.org/downloads/
In the kos-ports :
- liboggvorbis\liboggvorbis\libogg\src : put here the files from libogg-1.2.2.zip\libogg-1.2.2\src\ and the same for include
- liboggvorbis\liboggvorbis\libvorbis\lib : put here the files from libvorbis-1.3.2.zip\libvorbis-1.3.2\lib\ and the same for include
- update also the kos-ports/include/ogg and vorbis with the same files in include.
- the only thing I've changes is the config-types.h :

Code: Select all

#ifndef __CONFIG_TYPES_H__
#define __CONFIG_TYPES_H__

#include <sys/cdefs.h>
#include <arch/types.h>

/* these are filled in by configure */
typedef int16 ogg_int16_t;
typedef uint16 ogg_uint16_t;
typedef int32 ogg_int32_t;
typedef uint32 ogg_uint32_t;
typedef int64 ogg_int64_t;

#endif


- you just have to recompile the libs :

Code: Select all

cd kos-ports/liboggvorbis
make clean
make
- create a theora directory where you want, and get the last svn version :
svn co http://svn.xiph.org/trunk/theora
or download the last stable version from http://www.xiph.org/downloads/

- go into the theora directory, where you have debian,doc,examples... etc and create a directory "build"

- go to the lib directory

- Create this Makefile :

Code: Select all

# KallistiOS Ogg/Vorbis Decoder Library
#
# Library Makefile
# (c)2011 patbier
# Based on KOS Makefiles by Dan Potter

OBJS = analyze.o apiwrapper.o bitpack.o decapiwrapper.o decinfo.o decode.o dequant.o encapiwrapper.o encfrag.o encinfo.o encode.o enquant.o  fdct.o fragment.o huffdec.o huffenc.o idct.o info.o internal.o mathops.o mcenc.o quant.o rate.o state.o tokenize.o
KOS_CFLAGS += -I. -I../include -DLITTLE_ENDIAN=1

all: libtheora.a
libtheora.a: $(OBJS) 
	$(KOS_AR) rcs libtheora.a $(OBJS)
	cp $(OBJS) ../build
	cp libtheora.a ../build

clean:
	-rm -f $(OBJS) libtheora.a
	-rm -f ../build/*.o ../build/*.a

include $(KOS_BASE)/Makefile.rules
- run make, it normally builds it !

- to test it, in the theora directory, create a "dc" directory
create a Makefile :

Code: Select all

KOS_CFLAGS += -L../lib -I. -I../include
KOS_CFLAGS += -I. -I../src

TARGET = player.elf

OBJS = player.o

all: clean $(TARGET)

include $(KOS_BASE)/Makefile.rules

clean:
	-rm -f $(TARGET) $(OBJS)

$(TARGET): $(OBJS) 
	kos-cc -o $(TARGET) $(OBJS)  $(DATAOBJS) $(OBJEXTRA) -ltheora -loggvorbisplay -lm
- I create a player.c which is close to the example given, but it only decodes frame, no render.

Code: Select all

/********************************************************************
 *                                                                  *
 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
 *                                                                  *
 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
 * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
 *                                                                  *
 ********************************************************************

  function: example SDL player application; plays Ogg Theora files (with
            optional Vorbis audio second stream)
  last mod: $Id: player_example.c 17843 2011-02-15 17:19:12Z giles $

 ********************************************************************/

/* far more complex than most Ogg 'example' programs.  The complexity
   of maintaining A/V sync is pretty much unavoidable.  It's necessary
   to actually have audio/video playback to make the hard audio clock
   sync actually work.  If there's audio playback, there might as well
   be simple video playback as well...

   A simple 'demux and write back streams' would have been easier,
   it's true. */

#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#if !defined(_LARGEFILE_SOURCE)
#define _LARGEFILE_SOURCE
#endif
#if !defined(_LARGEFILE64_SOURCE)
#define _LARGEFILE64_SOURCE
#endif
#if !defined(_FILE_OFFSET_BITS)
#define _FILE_OFFSET_BITS 64
#endif

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifndef _REENTRANT
# define _REENTRANT
#endif

#include <kos.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include <signal.h>
#include "theora/theoradec.h"
#include "vorbis/codec.h"
//#include <SDL.h>

/* yes, this makes us OSS-specific for now. None of SDL, libao, libao2
   give us any way to determine hardware timing, and since the
   hard/kernel buffer is going to be most of or > a second, that's
   just a little bit important */
#if defined(__FreeBSD__)
#include <machine/soundcard.h>
#define AUDIO_DEVICE "/dev/audio"
#elif defined(__NetBSD__) || defined(__OpenBSD__)
#include <soundcard.h>
#define AUDIO_DEVICE "/dev/audio"
#else
//#include <sys/soundcard.h>
//#define AUDIO_DEVICE "/dev/dsp"
#endif
//#include <sys/ioctl.h>

/* Helper; just grab some more compressed bitstream and sync it for
   page extraction */
int buffer_data(FILE *in,ogg_sync_state *oy){
  char *buffer=ogg_sync_buffer(oy,4096);
  int bytes=fread(buffer,1,4096,in);
  ogg_sync_wrote(oy,bytes);
  return(bytes);
}

/* never forget that globals are a one-way ticket to Hell */
/* Ogg and codec state for demux/decode */
ogg_sync_state   oy;
ogg_page         og;
ogg_stream_state vo;
ogg_stream_state to;
th_info      ti;
th_comment   tc;
th_dec_ctx       *td;
th_setup_info    *ts;
vorbis_info      vi;
vorbis_dsp_state vd;
vorbis_block     vb;
vorbis_comment   vc;
th_pixel_fmt     px_fmt;

int              theora_p=0;
int              vorbis_p=0;
int              stateflag=0;

/* SDL Video playback structures */
//SDL_Surface *screen;
//SDL_Overlay *yuv_overlay;
//SDL_Rect rect;
unsigned char *RGBbuffer;

#define OC_CLAMP255(_x)     ((unsigned char)((((_x)<0)-1)&((_x)|-((_x)>255))))

/* single frame video buffering */
int          videobuf_ready=0;
ogg_int64_t  videobuf_granulepos=-1;
double       videobuf_time=0;

/* single audio fragment audio buffering */
int          audiobuf_fill=0;
int          audiobuf_ready=0;
ogg_int16_t *audiobuf;
ogg_int64_t  audiobuf_granulepos=0; /* time position of last sample */

/* audio / video synchronization tracking:

Since this will make it to Google at some point and lots of people
search for how to do this, a quick rundown of a practical A/V sync
strategy under Linux [the UNIX where Everything Is Hard].  Naturally,
this works on other platforms using OSS for sound as well.

In OSS, we don't have reliable access to any precise information on
the exact current playback position (that, of course would have been
too easy; the kernel folks like to keep us app people working hard
doing simple things that should have been solved once and abstracted
long ago).  Hopefully ALSA solves this a little better; we'll probably
use that once ALSA is the standard in the stable kernel.

We can't use the system clock for a/v sync because audio is hard
synced to its own clock, and both the system and audio clocks suffer
from wobble, drift, and a lack of accuracy that can be guaranteed to
add a reliable percent or so of error.  After ten seconds, that's
100ms.  We can't drift by half a second every minute.

Although OSS can't generally tell us where the audio playback pointer
is, we do know that if we work in complete audio fragments and keep
the kernel buffer full, a blocking select on the audio buffer will
give us a writable fragment immediately after playback finishes with
it.  We assume at that point that we know the exact number of bytes in
the kernel buffer that have not been played (total fragments minus
one) and calculate clock drift between audio and system then (and only
then).  Damp the sync correction fraction, apply, and walla: A
reliable A/V clock that even works if it's interrupted. */

long         audiofd_totalsize=-1;
int          audiofd_fragsize;      /* read and write only complete fragments
                                       so that SNDCTL_DSP_GETOSPACE is
                                       accurate immediately after a bank
                                       switch */
int          audiofd=-1;
ogg_int64_t  audiofd_timer_calibrate=-1;










/* helper: push a page into the appropriate steam */
/* this can be done blindly; a stream won't accept a page
                that doesn't belong to it */
static int queue_page(ogg_page *page){
  if(theora_p)ogg_stream_pagein(&to,page);
  if(vorbis_p)ogg_stream_pagein(&vo,page);
  return 0;
}
/* Report the encoder-specified colorspace for the video, if any.
   We don't actually make use of the information in this example;
   a real player should attempt to perform color correction for
   whatever display device it supports. */
static void report_colorspace(th_info *ti)
{
    switch(ti->colorspace){
      case TH_CS_UNSPECIFIED:
        /* nothing to report */
        break;;
      case TH_CS_ITU_REC_470M:
        printf("  encoder specified ITU Rec 470M (NTSC) color.\n");
        break;;
      case TH_CS_ITU_REC_470BG:
        printf("  encoder specified ITU Rec 470BG (PAL) color.\n");
        break;;
      default:
        printf("warning: encoder specified unknown colorspace (%d).\n",
            ti->colorspace);
        break;;
    }
}
/* dump the theora (or vorbis) comment header */
static int dump_comments(th_comment *tc){
  int i, len;
  char *value;
  FILE *out=stdout;

  printf("Encoded by %s\n",tc->vendor);
  if(tc->comments){
    printf("theora comment header:\n");
    for(i=0;i<tc->comments;i++){
      if(tc->user_comments[i]){
        len=tc->comment_lengths[i];
        value=malloc(len+1);
        memcpy(value,tc->user_comments[i],len);
        value[len]='\0';
        //fprintf(out, "\t%s\n", value);
        free(value);
      }
    }
  }
  return(0);
}

static void open_audio(){}
/* clean quit on Ctrl-C for SDL and thread shutdown as per SDL example
   (we don't use any threads, but libSDL does) */
int got_sigint=0;
static void sigint_handler (int signal) {
  got_sigint = 1;
}

static void open_video(void){}
/* call this only immediately after unblocking from a full kernel
   having a newly empty fragment or at the point of DMA restart */
void audio_calibrate_timer(int restart){
  struct timeval tv;
  ogg_int64_t current_sample;
  ogg_int64_t new_time;

  gettimeofday(&tv,0);
  new_time=tv.tv_sec*1000+tv.tv_usec/1000;

  if(restart){
    current_sample=audiobuf_granulepos-audiobuf_fill/2/vi.channels;
  }else
    current_sample=audiobuf_granulepos-
      (audiobuf_fill+audiofd_totalsize-audiofd_fragsize)/2/vi.channels;

  new_time-=1000*current_sample/vi.rate;

  audiofd_timer_calibrate=new_time;
}

/* get relative time since beginning playback, compensating for A/V
   drift */
double get_time(){
  static ogg_int64_t last=0;
  static ogg_int64_t up=0;
  ogg_int64_t now;
  struct timeval tv;

  gettimeofday(&tv,0);
  now=tv.tv_sec*1000+tv.tv_usec/1000;

  if(audiofd_timer_calibrate==-1)audiofd_timer_calibrate=last=now;

  if(audiofd<0){
    /* no audio timer to worry about, we can just use the system clock */
    /* only one complication: If the process is suspended, we should
       reset timing to account for the gap in play time.  Do it the
       easy/hack way */
    if(now-last>1000)audiofd_timer_calibrate+=(now-last);
    last=now;
  }

  if(now-up>200){
    double timebase=(now-audiofd_timer_calibrate)*.001;
    int hundredths=timebase*100-(long)timebase*100;
    int seconds=(long)timebase%60;
    int minutes=((long)timebase/60)%60;
    int hours=(long)timebase/3600;

    printf("   Playing: %d:%02d:%02d.%02d                       \r",
            hours,minutes,seconds,hundredths);
    up=now;
  }

  return (now-audiofd_timer_calibrate)*.001;

}

void audio_write_nonblocking(void){}

static void audio_close(void){}
static void video_write(void){}











int main(int argc,char *const *argv){

    int pp_level_max;
  int pp_level;
  int pp_inc;
  int i,j;
  ogg_packet op;

  FILE *infile = stdin;

  int frames = 0;
  int dropped = 0;
  
  	vid_set_mode (DM_640x480, PM_RGB565);
    pvr_init_defaults();  
  printf("Debut Theora\n\n");  
  infile=fopen("/cd/Movie.OGG","rb");
  if(infile==NULL){
    printf("Unable to open '%s' for playback.\n", argv[1]);
    exit(1);
  }
  
  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Vorbis structures needed in header parsing */
  vorbis_info_init(&vi);
  vorbis_comment_init(&vc);

  /* init supporting Theora structures needed in header parsing */
  th_comment_init(&tc);
  th_info_init(&ti);

  /* Ogg file open; parse the headers */
  /* Only interested in Vorbis/Theora streams */
  while(!stateflag){
    int ret=buffer_data(infile,&oy);
    if(ret==0)break;
    while(ogg_sync_pageout(&oy,&og)>0){
      ogg_stream_state test;

      /* is this a mandated initial header? If not, stop parsing */
      if(!ogg_page_bos(&og)){
        /* don't leak the page; get it into the appropriate stream */
        queue_page(&og);
        stateflag=1;
        break;
      }

      ogg_stream_init(&test,ogg_page_serialno(&og));
      ogg_stream_pagein(&test,&og);
      ogg_stream_packetout(&test,&op);


      /* identify the codec: try theora */
      if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){
        /* it is theora */
        memcpy(&to,&test,sizeof(test));
        theora_p=1;
      }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
        /* it is vorbis */
        memcpy(&vo,&test,sizeof(test));
        vorbis_p=1;
      }else{
        /* whatever it is, we don't care about it */
        ogg_stream_clear(&test);
      }
    }
    /* fall through to non-bos page parsing */
  }
  /* we're expecting more header packets. */
  while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
    int ret;

    /* look for further theora headers */
    while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
      if(ret<0){
        printf("Error parsing Theora stream headers; "
         "corrupt stream?\n");
        exit(1);
      }
      if(!th_decode_headerin(&ti,&tc,&ts,&op)){
        printf("Error parsing Theora stream headers; "
         "corrupt stream?\n");
        exit(1);
      }
      theora_p++;
    }

    /* look for more vorbis header packets */
    while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){
      if(ret<0){
        printf("Error parsing Vorbis stream headers; corrupt stream?\n");
        exit(1);
      }
      if(vorbis_synthesis_headerin(&vi,&vc,&op)){
        printf("Error parsing Vorbis stream headers; corrupt stream?\n");
        exit(1);
      }
      vorbis_p++;
      if(vorbis_p==3)break;
    }

    /* The header pages/packets will arrive before anything else we
       care about, or the stream is not obeying spec */

    if(ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og); /* demux into the appropriate stream */
    }else{
      int ret=buffer_data(infile,&oy); /* someone needs more data */
      if(ret==0){
        printf("End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }

  /* and now we have it all.  initialize decoders */
  if(theora_p){
    td=th_decode_alloc(&ti,ts);
    printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
           to.serialno,ti.pic_width,ti.pic_height,
           (double)ti.fps_numerator/ti.fps_denominator);
    px_fmt=ti.pixel_fmt;
    switch(ti.pixel_fmt){
      case TH_PF_420: printf(" 4:2:0 video\n"); break;
      case TH_PF_422: printf(" 4:2:2 video\n"); break;
      case TH_PF_444: printf(" 4:4:4 video\n"); break;
      case TH_PF_RSVD:
      default:
       printf(" video\n  (UNKNOWN Chroma sampling!)\n");
       break;
    }
    if(ti.pic_width!=ti.frame_width || ti.pic_height!=ti.frame_height)
      printf("  Frame content is %dx%d with offset (%d,%d).\n",
           ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y);
    report_colorspace(&ti);
    dump_comments(&tc);
    th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
     sizeof(pp_level_max));
    pp_level=pp_level_max;
    th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
    pp_inc=0;

    /*{
      int arg = 0xffff;
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg));
      arg=10;
      th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg));
    }*/
  }else{
    /* tear down the partial theora setup */
    th_info_clear(&ti);
    th_comment_clear(&tc);
  }

  th_setup_free(ts);

  if(vorbis_p){
    vorbis_synthesis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);
    printf("Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
            vo.serialno,vi.channels,vi.rate);
  }else{
    /* tear down the partial vorbis setup */
    vorbis_info_clear(&vi);
    vorbis_comment_clear(&vc);
  }

  /* open audio */
  if(vorbis_p)open_audio();

  /* open video */
  if(theora_p)open_video();
  printf("Apres open video& audio\n");
  /* install signal handler as SDL clobbered the default */
  signal (SIGINT, sigint_handler);
  printf("Apres signal\n");
  /* on to the main decode loop.  We assume in this example that audio
     and video start roughly together, and don't begin playback until
     we have a start frame for both.  This is not necessarily a valid
     assumption in Ogg A/V streams! It will always be true of the
     example_encoder (and most streams) though. */

  stateflag=0; /* playback has not begun */
  while(!got_sigint){
    /* we want a video and audio frame ready to go at all times.  If
       we have to buffer incoming, buffer the compressed data (ie, let
       ogg do the buffering) */
    while(vorbis_p && !audiobuf_ready){
      
      int ret;
      float **pcm;
      /* if there's pending, decoded audio, grab it */
      if((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0){
        int count=audiobuf_fill/2;
        int maxsamples=(audiofd_fragsize-audiobuf_fill)/2/vi.channels;
        for(i=0;i<ret && i<maxsamples;i++)
          for(j=0;j<vi.channels;j++){
            int val=rint(pcm[j][i]*32767.f);
            if(val>32767)val=32767;
            if(val<-32768)val=-32768;
            audiobuf[count++]=val;
          }
        vorbis_synthesis_read(&vd,i);
        audiobuf_fill+=i*vi.channels*2;
        if(audiobuf_fill==audiofd_fragsize)audiobuf_ready=1;
        if(vd.granulepos>=0)
          audiobuf_granulepos=vd.granulepos-ret+i;
        else
          audiobuf_granulepos+=i;

      }else{

        /* no pending audio; is there a pending packet to decode? */
        if(ogg_stream_packetout(&vo,&op)>0){
          if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
            vorbis_synthesis_blockin(&vd,&vb);
        }else   /* we need more data; break out to suck in another page */
          break;
      }
    }

    while(theora_p && !videobuf_ready){
      /* theora is one in, one out... */
      if(ogg_stream_packetout(&to,&op)>0){

        if(pp_inc){
          pp_level+=pp_inc;
          th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,
           sizeof(pp_level));
          pp_inc=0;
        }
        /*HACK: This should be set after a seek or a gap, but we might not have
           a granulepos for the first packet (we only have them for the last
           packet on a page), so we just set it as often as we get it.
          To do this right, we should back-track from the last packet on the
           page and compute the correct granulepos for the first packet after
           a seek or a gap.*/
        if(op.granulepos>=0){
          th_decode_ctl(td,TH_DECCTL_SET_GRANPOS,&op.granulepos,
           sizeof(op.granulepos));
        }
        if(th_decode_packetin(td,&op,&videobuf_granulepos)==0){
          videobuf_time=th_granule_time(td,videobuf_granulepos);
          frames++;
          printf("frame %d dropped %d\n",frames,dropped);
          /* is it already too old to be useful?  This is only actually
             useful cosmetically after a SIGSTOP.  Note that we have to
             decode the frame even if we don't show it (for now) due to
             keyframing.  Soon enough libtheora will be able to deal
             with non-keyframe seeks.  */

          if(videobuf_time>=get_time())
            videobuf_ready=1;
          else{
            /*If we are too slow, reduce the pp level.*/
            pp_inc=pp_level>0?-1:0;
            dropped++;
            printf("frame %d dropped %d\n",frames,dropped);
          }
        }

      }else
        break;
    }

    if(!videobuf_ready && !audiobuf_ready && feof(infile))break;

    if(!videobuf_ready || !audiobuf_ready){
      /* no data yet for somebody.  Grab another page */
      buffer_data(infile,&oy);
      while(ogg_sync_pageout(&oy,&og)>0){
        queue_page(&og);
      }
    }

    /* If playback has begun, top audio buffer off immediately. */
    if(stateflag) audio_write_nonblocking();

    /* are we at or past time for this video frame? */
    if(stateflag && videobuf_ready && videobuf_time<=get_time()){
      video_write();
      videobuf_ready=0;
    }

    if(stateflag &&
       (audiobuf_ready || !vorbis_p) &&
       (videobuf_ready || !theora_p) &&
       !got_sigint){
      /* we have an audio frame ready (which means the audio buffer is
         full), it's not time to play video, so wait until one of the
         audio buffer is ready or it's near time to play video */

      /* set up select wait on the audiobuffer and a timeout for video */
      struct timeval timeout;
      fd_set writefs;
      fd_set empty;
      int n=0;

      FD_ZERO(&writefs);
      FD_ZERO(&empty);
      if(audiofd>=0){
        FD_SET(audiofd,&writefs);
        n=audiofd+1;
      }

      if(theora_p){
        double tdiff;
        long milliseconds;
        tdiff=videobuf_time-get_time();
        /*If we have lots of extra time, increase the post-processing level.*/
        if(tdiff>ti.fps_denominator*0.25/ti.fps_numerator){
          pp_inc=pp_level<pp_level_max?1:0;
        }
        else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){
          pp_inc=pp_level>0?-1:0;
        }
        milliseconds=tdiff*1000-5;
        if(milliseconds>500)milliseconds=500;
        if(milliseconds>0){
          timeout.tv_sec=milliseconds/1000;
          timeout.tv_usec=(milliseconds%1000)*1000;

          //n=select(n,&empty,&writefs,&empty,&timeout);
          //if(n)audio_calibrate_timer(0);
        }
      }else{
        //select(n,&empty,&writefs,&empty,NULL);
      }
    }

    /* if our buffers either don't exist or are ready to go,
       we can begin playback */
    if((!theora_p || videobuf_ready) &&
       (!vorbis_p || audiobuf_ready))stateflag=1;
    /* same if we've run out of input */
    if(feof(infile))stateflag=1;

  }

  /* tear it all down */

  audio_close();
  //SDL_Quit();











  
  printf("\n");
  printf("\nDone.\n");

  return(0);

}

- compile it with make

- now you need a video file, I used "Super" to create a theora video file. I burned it on a cd.

- the decoder works but it seems slow.

So, if someone here tries and have a look, does it seem possible to optimize and use the libtheora ? I'd like to use a 320*240 with a reasonable bitrate (1000 kbs).

Another codec idea ?

Thanks for reading this long topic !
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Video Player for independant game / libtheora port first try

Post by PH3NOM »

Welcome to my world! Compiling any mulit-media library for DC is relatively easy.
Getting a player to work, with good speeds, is the hard part.

Check your PM's, I sent you a sample binary for XviD-DC.

I ported libtheora for DC sometime last year, it sounded promising.
It has the most well-developed sample application of any library I have seen, other than FFMpeg.
But soon realized how obscure the format is, and for my project this codec made no sense.
So I never got as far as getting the sample player to work, I stopped after porting the library.
As a codec for FMV in a game, libhteora does make a lot of sense.

I will look at the library again and see if I can apply any of the speed optimization Im using with LibXviD.
Can you upload a sample.ogm? I dont currenly have any encoders to support this codec and right now
I cant be bothered to..

Maybe someone with more knowledge can help; with the GPL license, does the entire source have to be released, or only the source of the GPL'd code?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Video Player for independant game / libtheora port first try

Post by BlueCrab »

PH3NOM wrote:Maybe someone with more knowledge can help; with the GPL license, does the entire source have to be released, or only the source of the GPL'd code?
The entire work derived from GPLed code must be released under terms compatible with the GPL. As you are linking the GPLed code into your code, your work becomes a derivative work, and thus must have its complete and total source code released under GPL-compatible terms (this even applies to dynamic linking).

Note, this doesn't mean that your code must be GPL-licensed, but it must be available under terms compliant with it. You're perfectly OK to release the code under a MORE permissive license than the GPL (so, your portion of the code can be under the two or three clause BSD license, for instance). You essentially must release the source code, and it must be under terms compatible with the GPL. Those are the requirements set by the license.
Ex-Cyber
DCEmu User with No Life
DCEmu User with No Life
Posts: 3641
Joined: Sat Feb 16, 2002 1:55 pm
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by Ex-Cyber »

BlueCrab wrote:this even applies to dynamic linking
That issue is extremely fuzzy.
"You know, I have a great, wonderful, really original method of teaching antitrust law, and it kept 80 percent of the students awake. They learned things. It was fabulous." -- Justice Stephen Breyer
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Video Player for independant game / libtheora port first try

Post by BlueCrab »

Ex-Cyber wrote:
BlueCrab wrote:this even applies to dynamic linking
That issue is extremely fuzzy.
Really? Most everything I've ever read has stated that it is the case that dynamic linking is still considered in the derivative work clause of the GPL. That, and the FSF has clearly stated that this is the intent: to make sure that proprietary code cannot make use of GPLed code directly, even through dynamic linking.

After all, that's what the LGPL was designed to facilitate. The LGPL, for the most part, is the GPL, but essentially allowing dynamic linking without the license requirements.

Anyway, its slightly off-topic anyway as we really don't have much of dynamic linking support in KOS anyway (yes, there is some, but it hasn't been touched in a long while, and knowing me, I probably unintentionally broke it at some point).

EDIT: Here's the FSF's take on dynamic linking (talking about plugins, but the whole thing still applies): http://www.gnu.org/licenses/gpl-faq.htm ... GPLPlugins
patbier
DC Developer
DC Developer
Posts: 152
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by patbier »

it's not off-topic, it's very interesting as gpl / lgpl licence are not easy to understand.

If I quote the http://www.gnu.org/licenses/gpl-faq.htm ... GPLPlugins
Can I release a non-free program that's designed to load a GPL-covered plug-in?

It depends on how the program invokes its plug-ins. For instance, if the program uses only simple fork and exec to invoke and communicate with plug-ins, then the plug-ins are separate programs, so the license of the plug-in makes no requirements about the main program.

If the program dynamically links plug-ins, and they make function calls to each other and share data structures, we believe they form a single program, which must be treated as an extension of both the main program and the plug-ins. In order to use the GPL-covered plug-ins, the main program must be released under the GPL or a GPL-compatible free software license, and that the terms of the GPL must be followed when the main program is distributed for use with these plug-ins.

If the program dynamically links plug-ins, but the communication between them is limited to invoking the ‘main’ function of the plug-in with some options and waiting for it to return, that is a borderline case.

Using shared memory to communicate with complex data structures is pretty much equivalent to dynamic linking.
This is very interesting. If i understand it, there is maybe a way to do it :

making separate binaries like the basic/exec example in KOS :

Code: Select all

int main(int argc, char **argv) {
	file_t f;
	void *subelf;

	/* Print a hello */
	printf("\n\nHello world from the exec.elf process\n");

	/* Map the sub-elf */
	f = fs_open("/rd/sub.bin", O_RDONLY);
	assert( f );
	subelf = fs_mmap(f);
	assert( subelf );

	/* Tell exec to replace us */
	printf("sub.bin mapped at %08x, jumping to it!\n\n\n", subelf);
	arch_exec(subelf, fs_total(f));

	/* Shouldn't get here */
	assert_msg( false, "exec call failed" );

	return 0;
}
main binary just load a video player binary to read the video intro, then it loads the main binary of the game. So only the video player binary uses the GPL stuff, and it is only concerned to have its source released.

Am I right ?
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
patbier
DC Developer
DC Developer
Posts: 152
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by patbier »

I recently contact Mike to have his opinion, and he decided to compete this challenge : http://multimedia.cx/eggs/playing-video ... dreamcast/

Very very interesting !
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
Ex-Cyber
DCEmu User with No Life
DCEmu User with No Life
Posts: 3641
Joined: Sat Feb 16, 2002 1:55 pm
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by Ex-Cyber »

Well, that is where you get into the murky territory of this proclamation:
Using shared memory to communicate with complex data structures is pretty much equivalent to dynamic linking.
The following is just my opinion, and I'm not a lawyer. I'm not aware of any actual legal standard with respect to the copyright status of dynamic linking. All I've ever seen is speculation. Some of that follows.

I think the FSF's explanation kind of dances around the main point, which is this: does your program depend on a specific library/program, or is it using a standard interface that can be readily handled without copying code from the original library/program? If it's the former, any separation you try to perform is arguably just sophistry. If it's the latter, the user is free to link someone else's code (which could in principle be compatible).

Either way, I'd say that the important thing is not the FSF's position, but the position of the copyright holder for the code you want to use. They may or may not agree with the FSF on this point, and your best bet for avoiding trouble is generally to respect the wishes of the copyright holder.
"You know, I have a great, wonderful, really original method of teaching antitrust law, and it kept 80 percent of the students awake. They learned things. It was fabulous." -- Justice Stephen Breyer
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Video Player for independant game / libtheora port first try

Post by BlueCrab »

patbier wrote:main binary just load a video player binary to read the video intro, then it loads the main binary of the game. So only the video player binary uses the GPL stuff, and it is only concerned to have its source released.

Am I right ?
Yes, that is completely correct. They would be two completely separate programs as far as things were concerned, so that would skirt around the GPL requirements.
Either way, I'd say that the important thing is not the FSF's position, but the position of the copyright holder for the code you want to use. They may or may not agree with the FSF on this point, and your best bet for avoiding trouble is generally to respect the wishes of the copyright holder.
Indeed, that is always the case that the copyright holder is the one who really matters. After all, he/she is the only person who could actually complain about it, in a legal sense. The FSF's position is the one I would take when tasked with the question, but at the same time, if someone were to ask me and present a very good reason to do so, I'd likely be inclined to license stuff to them under a more lenient license.
User avatar
PH3NOM
DC Developer
DC Developer
Posts: 576
Joined: Fri Jun 18, 2010 9:29 pm
Has thanked: 0
Been thanked: 5 times

Re: Video Player for independant game / libtheora port first try

Post by PH3NOM »

BlueCrab wrote:
patbier wrote:main binary just load a video player binary to read the video intro, then it loads the main binary of the game. So only the video player binary uses the GPL stuff, and it is only concerned to have its source released.

Am I right ?
Yes, that is completely correct. They would be two completely separate programs as far as things were concerned, so that would skirt around the GPL requirements.
I believe some retail Dreamcast applications used this method; the 1st_read.bin is just the Mpeg Sofdec, that plays the intro videos then exits and launches the main game binary.

So, in this method, it is possible to use GPL'd code without releasing the full game source.
patbier
DC Developer
DC Developer
Posts: 152
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by patbier »

Looking at the xvid FAQ, it seems not possible, but I'm not sure my english is not perfect.
Someone can read it ? http://www.xvid.org/FAQ.42.0.html
Thanks
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5652
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Video Player for independant game / libtheora port first try

Post by BlueCrab »

The GPL specifically allows "mere aggregation", which is distributing two binaries together. Technically loading a binary and running it with arch_exec() is "mere aggregation", otherwise you wouldn't be able to run GPLed programs from a closed-source OS/Shell/etc.

Granted, in the case of Dreamcast stuff and the way it was proposed in this thread to skirt the GPL's requirements, its a bit more murky in my opinion, since your (closed-source) program is directly tied and dependent on the GPLed component. In this way, it almost acts more like a dynamic linking situation. I'd personally probably be a bit annoyed if someone did this with a GPLed program that I wrote to skirt the license requirements.

In the end, the best course of action is to follow the will of the copyright holder. If in doubt as to what they consider infringement, ask them. Also, if you're really looking to put this into a closed-source product that you intend to charge money for or something like that, consider how you would feel if you were in their shoes. Would you like to essentially see someone profiting off of your work without contributing anything back to you?

I believe heavily in using the GPL to protect my works. That's why almost everything I do is licensed under the GPL, LGPL, or AGPL (other than KOS).
Ex-Cyber
DCEmu User with No Life
DCEmu User with No Life
Posts: 3641
Joined: Sat Feb 16, 2002 1:55 pm
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by Ex-Cyber »

Okay, I misunderstood the intent of the code snippet; that should be mere aggregation and fine under the GPL if I'm reading it right this time.
"You know, I have a great, wonderful, really original method of teaching antitrust law, and it kept 80 percent of the students awake. They learned things. It was fabulous." -- Justice Stephen Breyer
patbier
DC Developer
DC Developer
Posts: 152
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first try

Post by patbier »

Mike continues his great work : http://multimedia.cx/eggs/roq-on-dreamcast/#more-3210
It is very very interesting. He gives me real time comments on his work in progress, and this is probably the best video solution for KOS projects. He has a "problem" with cd reading speed, so perhaps someone has experience and gives him advices.
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
User avatar
Christuserloeser
Moderator
Moderator
Posts: 5948
Joined: Thu Aug 28, 2003 12:16 am
Location: DCEvolution.net
Has thanked: 10 times
Been thanked: 0
Contact:

Re: Video Player for independant game / libtheora port first

Post by Christuserloeser »

*bump*



I think for this kind of video, the GIF player of Beats of Rage would be perfect!?

see Beats of Rage intro:


It supports 256 individual colors per scene (e.g. 10 sec for scene 1, cut to scene 2 for 2 sec, cut to scene 3 for 5 sec, cut to scene for 10 sec = all with 256 colors each).

Maybe talk to Senile Team about that?
Insane homebrew collector.
patbier
DC Developer
DC Developer
Posts: 152
Joined: Fri Aug 29, 2003 1:25 am
Has thanked: 0
Been thanked: 0

Re: Video Player for independant game / libtheora port first

Post by patbier »

Thanks for the idea Christuserloeser
But, with the help of Mike Melanson and Ph3nom, we achieved in porting the Roq video engine to the dreamcast (see topic : viewtopic.php?f=29&t=100995)
And it now works very very nice. The video renders on the dreamcast very close to the youtube render !
ImageAlice Dreams Tournament Dreamcast fans : http://www.facebook.com/alicedreamst
In August 2015, we had to change "Dynamite Dreams" name to "Alice Dreams Tournament"
Post Reply