[xiph-commits] r12863 - in trunk/theora: examples lib lib/enc
j at svn.xiph.org
j at svn.xiph.org
Sun Apr 15 02:49:31 PDT 2007
Author: j
Date: 2007-04-15 02:49:31 -0700 (Sun, 15 Apr 2007)
New Revision: 12863
Removed:
trunk/theora/lib/enc/pp.c
trunk/theora/lib/enc/pp.h
Modified:
trunk/theora/examples/dump_video.c
trunk/theora/examples/player_example.c
trunk/theora/lib/Makefile.am
Log:
- remove leftover from old decoder(pp.?)
- user new decoder api in player_example / dump_video
Modified: trunk/theora/examples/dump_video.c
===================================================================
--- trunk/theora/examples/dump_video.c 2007-04-14 07:51:10 UTC (rev 12862)
+++ trunk/theora/examples/dump_video.c 2007-04-15 09:49:31 UTC (rev 12863)
@@ -5,7 +5,7 @@
* 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-2004 *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2006 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
@@ -18,42 +18,32 @@
/* By Mauricio Piacentini (mauricio at xiph.org) */
/* simply dump decoded YUV data, for verification of theora bitstream */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#define _GNU_SOURCE
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
-#ifndef WIN32
#include <unistd.h>
-#endif
#include <stdlib.h>
#include <string.h>
+#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/timeb.h>
-
+/*Yes, yes, we're going to hell.*/
#if defined(_WIN32)
#include <io.h>
#endif
-
#include <fcntl.h>
#include <math.h>
#include <signal.h>
-
#include "getopt.h"
-#include "theora/theora.h"
+#include "theora/theoradec.h"
-
-
const char *optstring = "o:rf";
struct option options [] = {
{"output",required_argument,NULL,'o'},
- {"raw",no_argument, NULL, 'r'}, /* Disable YUV4MPEG2 headers if set */
+ {"raw",no_argument, NULL,'r'}, /*Disable YUV4MPEG2 headers:*/
{"fps-only",no_argument, NULL, 'f'}, /* Only interested in fps of decode loop */
{NULL,0,NULL,0}
};
@@ -69,22 +59,24 @@
/* 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;
-theora_info ti;
-theora_comment tc;
-theora_state td;
+ogg_sync_state oy;
+ogg_page og;
+ogg_stream_state vo;
+ogg_stream_state to;
+th_info ti;
+th_comment tc;
+th_setup_info *ts;
+th_dec_ctx *td;
int theora_p=0;
+int theora_processing_headers;
int stateflag=0;
/* single frame video buffering */
int videobuf_ready=0;
ogg_int64_t videobuf_granulepos=-1;
double videobuf_time=0;
-int raw = 0;
+int raw=0;
FILE* outfile = NULL;
@@ -93,57 +85,75 @@
got_sigint = 1;
}
-/* this is a nop in the current implementation. we could
- open a file here or something if so moved. */
+static th_ycbcr_buffer ycbcr;
+
+static void stripe_decoded(th_ycbcr_buffer _dst,th_ycbcr_buffer _src,
+ int _fragy0,int _fragy_end){
+ int pli;
+ for(pli=0;pli<3;pli++){
+ int yshift;
+ int y_end;
+ int y;
+ yshift=pli!=0&&!(ti.pixel_fmt&2);
+ y_end=_fragy_end<<3-yshift;
+ for(y=_fragy0<<3-yshift;y<y_end;y++){
+ memcpy(_dst[pli].data+y*_dst[pli].ystride,
+ _src[pli].data+y*_src[pli].ystride,_src[pli].width);
+ }
+ }
+}
+
static void open_video(void){
- return;
+ th_stripe_callback cb;
+ int pli;
+ /*Here we allocate a buffer so we can use the striped decode feature.
+ There's no real reason to do this in this application, because we want to
+ write to the file top-down, but the frame gets decoded bottom up, so we
+ have to buffer it all anyway.
+ But this illustrates how the API works.*/
+ for(pli=0;pli<3;pli++){
+ int xshift;
+ int yshift;
+ xshift=pli!=0&&!(ti.pixel_fmt&1);
+ yshift=pli!=0&&!(ti.pixel_fmt&2);
+ ycbcr[pli].data=(unsigned char *)malloc(
+ (ti.frame_width>>xshift)*(ti.frame_height>>yshift)*sizeof(char));
+ ycbcr[pli].ystride=ti.frame_width>>xshift;
+ ycbcr[pli].width=ti.frame_width>>xshift;
+ ycbcr[pli].height=ti.frame_height>>yshift;
+ }
+ /*Similarly, since ycbcr is a global, there's no real reason to pass it as
+ the context.
+ In a more object-oriented decoder, we could pass the "this" pointer
+ instead (though in C++ platform-dependent calling convention differences
+ prevent us from using a real member function pointer).*/
+ cb.ctx=ycbcr;
+ cb.stripe_decoded=(th_stripe_decoded_func)stripe_decoded;
+ th_decode_ctl(td,TH_DECCTL_SET_STRIPE_CB,&cb,sizeof(cb));
}
-/* write out the planar YUV frame, uncropped */
static void video_write(void){
+ int pli;
int i;
- yuv_buffer yuv;
- theora_decode_YUVout(&td,&yuv);
+ /*Uncomment the following to do normal, non-striped decoding.
+ th_ycbcr_buffer ycbcr;
+ th_decode_ycbcr_out(td,ycbcr);*/
+ fprintf(outfile, "FRAME\n");
- if(outfile){
- if(!raw)
- fprintf(outfile, "FRAME\n");
- for(i=0;i<yuv.y_height;i++)
- fwrite(yuv.y+yuv.y_stride*i, 1, yuv.y_width, outfile);
- for(i=0;i<yuv.uv_height;i++)
- fwrite(yuv.u+yuv.uv_stride*i, 1, yuv.uv_width, outfile);
- for(i=0;i<yuv.uv_height;i++)
- fwrite(yuv.v+yuv.uv_stride*i, 1, yuv.uv_width, outfile);
- }
-
-}
-/* dump the theora comment header */
-static int dump_comments(theora_comment *tc){
- int i, len;
- char *value;
- FILE *out=stdout;
-
- fprintf(out,"Encoded by %s\n",tc->vendor);
- if(tc->comments){
- fprintf(out, "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);
- }
+ for(pli=0;pli<3;pli++){
+ for(i=0;i<ycbcr[pli].height;i++){
+ fwrite(ycbcr[pli].data+ycbcr[pli].ystride*i, 1,
+ ycbcr[pli].width, outfile);
}
}
- return(0);
}
-/* helper: push a page into the steam for packetization */
+/* 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,&og);
+ if(theora_p)ogg_stream_pagein(&to,page);
return 0;
}
@@ -162,15 +172,16 @@
int long_option_index;
int c;
+ int frames = 0;
+
+ FILE *infile = stdin;
+ outfile = stdout;
+
struct timeb start;
struct timeb after;
struct timeb last;
int fps_only=0;
- int frames=0;
- FILE *infile = stdin;
- outfile = stdout;
-
#ifdef _WIN32 /* We need to set stdin/stdout to binary mode on windows. */
/* Beware the evil ifdef. We avoid these where we can, but this one we
cannot. Don't add any more, you'll probably go to hell if you do. */
@@ -194,16 +205,16 @@
break;
case 'r':
- raw = 1;
- break;
-
+ raw=1;
+ break;
+
case 'f':
fps_only = 1;
- outfile=NULL;
+ outfile = NULL;
break;
-
- default:
- usage();
+
+ default:
+ usage();
}
}
if(optind<argc){
@@ -218,34 +229,19 @@
}
}
-
- /*
- Ok, Ogg parsing. The idea here is we have a bitstream
- that is made up of Ogg pages. The libogg sync layer will
- find them for us. There may be pages from several logical
- streams interleaved; we find the first theora stream and
- ignore any others.
-
- Then we pass the pages for our stream to the libogg stream
- layer which assembles our original set of packets out of
- them. It's the packets that libtheora actually knows how
- to handle.
- */
-
/* 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 */
- theora_comment_init(&tc);
- theora_info_init(&ti);
+ th_comment_init(&tc);
+ th_info_init(&ti);
/* Ogg file open; parse the headers */
-
- /* Vorbis and Theora both depend on some initial header packets
- for decoder setup and initialization. We retrieve these first
- before entering the main decode loop. */
-
- /* Only interested in Theora streams */
+ /* Only interested in Vorbis/Theora streams */
while(!stateflag){
int ret=buffer_data(infile,&oy);
if(ret==0)break;
@@ -262,47 +258,54 @@
ogg_stream_init(&test,ogg_page_serialno(&og));
ogg_stream_pagein(&test,&og);
- ogg_stream_packetout(&test,&op);
+ ogg_stream_packetpeek(&test,&op);
/* identify the codec: try theora */
- if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
- /* it is theora -- save this stream state */
+ if(!theora_p && (theora_processing_headers=
+ th_decode_headerin(&ti,&tc,&ts,&op))>=0){
+ /* it is theora */
memcpy(&to,&test,sizeof(test));
theora_p=1;
+ /*Advance past the successfully processed header.*/
+ if(theora_processing_headers)ogg_stream_packetout(&to,NULL);
}else{
/* whatever it is, we don't care about it */
ogg_stream_clear(&test);
}
}
- /* fall through to non-initial page parsing */
+ /* fall through to non-bos page parsing */
}
/* we're expecting more header packets. */
- while(theora_p && theora_p<3){
+ while(theora_p && theora_processing_headers){
int ret;
/* look for further theora headers */
- while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
- if(ret<0){
- fprintf(stderr,"Error parsing Theora stream headers; corrupt stream?\n");
- exit(1);
- }
- if(theora_decode_header(&ti,&tc,&op)){
+ while(theora_processing_headers&&(ret=ogg_stream_packetpeek(&to,&op))){
+ if(ret<0)continue;
+ theora_processing_headers=th_decode_headerin(&ti,&tc,&ts,&op);
+ if(theora_processing_headers<0){
printf("Error parsing Theora stream headers; corrupt stream?\n");
exit(1);
}
+ else if(theora_processing_headers>0){
+ /*Advance past the successfully processed header.*/
+ ogg_stream_packetout(&to,NULL);
+ }
theora_p++;
- if(theora_p==3)break;
}
+ /*Stop now so we don't fail if there aren't enough pages in a short
+ stream.*/
+ if(!(theora_p && theora_processing_headers))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 stream state */
+ queue_page(&og); /* demux into the appropriate stream */
}else{
- int ret=buffer_data(infile,&oy); /* need more data */
+ int ret=buffer_data(infile,&oy); /* someone needs more data */
if(ret==0){
fprintf(stderr,"End of file while searching for codec headers.\n");
exit(1);
@@ -310,51 +313,35 @@
}
}
- /* Now we have all the required headers. initialize the decoder. */
+ /* and now we have it all. initialize decoders */
if(theora_p){
- theora_decode_init(&td,&ti);
- fprintf(stderr,"Ogg logical stream %x is Theora %dx%d %.02f fps video\nEncoded frame content is %dx%d with %dx%d offset\n",
- (unsigned int)to.serialno,ti.width,ti.height,
- (double)ti.fps_numerator/ti.fps_denominator,
- ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
+ td=th_decode_alloc(&ti,ts);
+ fprintf(stderr,"Ogg logical stream %lx is Theora %dx%d %.02f fps video\nEncoded frame content is %dx%d with %dx%d offset\n",
+ to.serialno,ti.frame_width,ti.frame_height,
+ (double)ti.fps_numerator/ti.fps_denominator,
+ ti.pic_width, ti.pic_height, ti.pic_x, ti.pic_y);
}else{
/* tear down the partial theora setup */
- theora_info_clear(&ti);
- theora_comment_clear(&tc);
+ th_info_clear(&ti);
+ th_comment_clear(&tc);
}
+ /*Either way, we're done with the codec setup data.*/
+ th_setup_free(ts);
/* open video */
if(theora_p)open_video();
- if(!raw && outfile)
+ if(!raw && outfile){
fprintf(outfile, "YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\n",
- ti.width, ti.height, ti.fps_numerator, ti.fps_denominator, 'p',
- ti.aspect_numerator, ti.aspect_denominator);
+ ti.pic_width,ti.pic_height,ti.fps_numerator,ti.fps_denominator,'p',
+ ti.aspect_numerator,ti.aspect_denominator);
+ }
/* install signal handler */
signal (SIGINT, sigint_handler);
- /* Finally the main decode loop.
+ /* on to the main decode loop.*/
- It's one Theora packet per frame, so this is pretty
- straightforward if we're not trying to maintain sync
- with other multiplexed streams.
-
- the videobuf_ready flag is used to maintain the input
- buffer in the libogg stream state. If there's no output
- frame available at the end of the decode step, we must
- need more input data. We could simplify this by just
- using the return code on ogg_page_packetout(), but the
- flag system extends easily to the case were you care
- about more than one multiplexed stream (like with audio
- playback). In that case, just maintain a flag for each
- decoder you care about, and pull data when any one of
- them stalls.
-
- videobuf_time holds the presentation time of the currently
- buffered video frame. We ignore this value.
- */
-
stateflag=0; /* playback has not begun */
/* queue any remaining pages from data we buffered but that did not
contain headers */
@@ -368,19 +355,19 @@
}
while(!got_sigint){
-
+
while(theora_p && !videobuf_ready){
/* theora is one in, one out... */
if(ogg_stream_packetout(&to,&op)>0){
- theora_decode_packetin(&td,&op);
- videobuf_granulepos=td.granulepos;
- videobuf_time=theora_granule_time(&td,videobuf_granulepos);
- videobuf_ready=1;
- frames++;
- if(fps_only)
- ftime(&after);
-
+ if(th_decode_packetin(td,&op,&videobuf_granulepos)>=0){
+ videobuf_time=th_granule_time(td,videobuf_granulepos);
+ videobuf_ready=1;
+ frames++;
+ if(fps_only)
+ ftime(&after);
+ }
+
}else
break;
}
@@ -389,7 +376,7 @@
long ms =
after.time*1000.+after.millitm-
(last.time*1000.+last.millitm);
-
+
if(ms>500 || fps_only==1 ||
(feof(infile) && !videobuf_ready)){
float file_fps = (float)ti.fps_numerator/ti.fps_denominator;
@@ -405,10 +392,9 @@
}
}
+ if(!videobuf_ready && feof(infile))break;
- if(!videobuf_ready && feof(infile))break;
-
- if(!videobuf_ready){
+ if(!videobuf_ready ){
/* no data yet for somebody. Grab another page */
buffer_data(infile,&oy);
while(ogg_sync_pageout(&oy,&og)>0){
@@ -416,26 +402,28 @@
}
}
/* dumpvideo frame, and get new one */
- else video_write();
+ else
+ if(outfile)video_write();
videobuf_ready=0;
}
- /* end of decoder loop -- close everything */
+ /* close everything */
if(theora_p){
ogg_stream_clear(&to);
- theora_clear(&td);
- theora_comment_clear(&tc);
- theora_info_clear(&ti);
+ th_decode_free(td);
+ th_comment_clear(&tc);
+ th_info_clear(&ti);
}
ogg_sync_clear(&oy);
if(infile && infile!=stdin)fclose(infile);
+ if(outfile && outfile!=stdout)fclose(outfile);
- fprintf(stderr,
- "\n "
- "\nDone.\n");
+ fprintf(stderr, "\n\n%d frames\n", frames);
+ fprintf(stderr, "\nDone.\n");
+
return(0);
}
Modified: trunk/theora/examples/player_example.c
===================================================================
--- trunk/theora/examples/player_example.c 2007-04-14 07:51:10 UTC (rev 12862)
+++ trunk/theora/examples/player_example.c 2007-04-15 09:49:31 UTC (rev 12863)
@@ -48,7 +48,7 @@
#include <fcntl.h>
#include <math.h>
#include <signal.h>
-#include "theora/theora.h"
+#include "theora/theoradec.h"
#include "vorbis/codec.h"
#include <SDL.h>
@@ -83,15 +83,17 @@
ogg_page og;
ogg_stream_state vo;
ogg_stream_state to;
-theora_info ti;
-theora_comment tc;
-theora_state td;
+th_info ti;
+th_comment tc;
+th_setup_info *ts;
+th_dec_ctx *td;
vorbis_info vi;
vorbis_dsp_state vd;
vorbis_block vb;
vorbis_comment vc;
int theora_p=0;
+int theora_processing_headers;
int vorbis_p=0;
int stateflag=0;
@@ -301,14 +303,14 @@
exit(1);
}
- screen = SDL_SetVideoMode(ti.frame_width, ti.frame_height, 0, SDL_SWSURFACE);
+ screen = SDL_SetVideoMode(ti.pic_width, ti.pic_height, 0, SDL_SWSURFACE);
if ( screen == NULL ) {
fprintf(stderr, "Unable to set %dx%d video: %s\n",
- ti.frame_width,ti.frame_height,SDL_GetError());
+ ti.pic_width,ti.pic_height,SDL_GetError());
exit(1);
}
- yuv_overlay = SDL_CreateYUVOverlay(ti.frame_width, ti.frame_height,
+ yuv_overlay = SDL_CreateYUVOverlay(ti.pic_width, ti.pic_height,
SDL_YV12_OVERLAY,
screen);
if ( yuv_overlay == NULL ) {
@@ -318,41 +320,44 @@
}
rect.x = 0;
rect.y = 0;
- rect.w = ti.frame_width;
- rect.h = ti.frame_height;
+ rect.w = ti.pic_width;
+ rect.h = ti.pic_height;
SDL_DisplayYUVOverlay(yuv_overlay, &rect);
}
static void video_write(void){
+ static const int planemap[3] = {0,2,1};
+ int pli;
+ int wscale, hscale;
int i;
- yuv_buffer yuv;
+ th_ycbcr_buffer ycbcr;
int crop_offset;
- theora_decode_YUVout(&td,&yuv);
+ th_decode_ycbcr_out(td,ycbcr);
+
/* Lock SDL_yuv_overlay */
if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) return;
}
if (SDL_LockYUVOverlay(yuv_overlay) < 0) return;
- /* let's draw the data (*yuv[3]) on a SDL screen (*screen) */
+ /* let's draw the data on a SDL screen (*screen) */
/* deal with border stride */
/* reverse u and v for SDL */
/* and crop input properly, respecting the encoded frame rect */
- crop_offset=ti.offset_x+yuv.y_stride*ti.offset_y;
- for(i=0;i<yuv_overlay->h;i++)
- memcpy(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i,
- yuv.y+crop_offset+yuv.y_stride*i,
- yuv_overlay->w);
- crop_offset=(ti.offset_x/2)+(yuv.uv_stride)*(ti.offset_y/2);
- for(i=0;i<yuv_overlay->h/2;i++){
- memcpy(yuv_overlay->pixels[1]+yuv_overlay->pitches[1]*i,
- yuv.v+crop_offset+yuv.uv_stride*i,
- yuv_overlay->w/2);
- memcpy(yuv_overlay->pixels[2]+yuv_overlay->pitches[2]*i,
- yuv.u+crop_offset+yuv.uv_stride*i,
- yuv_overlay->w/2);
+ /* problems may exist for odd frame rect for some encodings */
+ for (pli = 0; pli < 3; pli++) {
+ wscale = ycbcr[0].width / ycbcr[pli].width;
+ hscale = ycbcr[0].height / ycbcr[pli].height;
+ crop_offset = (ti.pic_x / wscale)
+ + (ycbcr[pli].ystride)
+ * (ti.pic_y / hscale);
+ for(i=0;i<yuv_overlay->h / hscale;i++)
+ memcpy(yuv_overlay->pixels[planemap[pli]]
+ + yuv_overlay->pitches[planemap[pli]]*i,
+ ycbcr[pli].data+crop_offset+ycbcr[pli].ystride*i,
+ yuv_overlay->w / wscale);
}
/* Unlock SDL_yuv_overlay */
@@ -367,7 +372,7 @@
}
/* dump the theora (or vorbis) comment header */
-static int dump_comments(theora_comment *tc){
+static int dump_comments(th_comment *tc){
int i, len;
char *value;
FILE *out=stdout;
@@ -393,16 +398,16 @@
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(theora_info *ti)
+static void report_colorspace(th_info *ti)
{
switch(ti->colorspace){
- case OC_CS_UNSPECIFIED:
+ case TH_CS_UNSPECIFIED:
/* nothing to report */
break;;
- case OC_CS_ITU_REC_470M:
+ case TH_CS_ITU_REC_470M:
fprintf(stderr," encoder specified ITU Rec 470M (NTSC) color.\n");
break;;
- case OC_CS_ITU_REC_470BG:
+ case TH_CS_ITU_REC_470BG:
fprintf(stderr," encoder specified ITU Rec 470BG (PAL) color.\n");
break;;
default:
@@ -416,7 +421,7 @@
/* 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,&og);
+ if(theora_p)ogg_stream_pagein(&to,page);
if(vorbis_p)ogg_stream_pagein(&vo,&og);
return 0;
}
@@ -431,11 +436,17 @@
int main(int argc,char *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;
+
#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
/* Beware the evil ifdef. We avoid these where we can, but this one we
cannot. Don't add any more, you'll probably go to hell if you do. */
@@ -463,8 +474,8 @@
vorbis_comment_init(&vc);
/* init supporting Theora structures needed in header parsing */
- theora_comment_init(&tc);
- theora_info_init(&ti);
+ th_comment_init(&tc);
+ th_info_init(&ti);
/* Ogg file open; parse the headers */
/* Only interested in Vorbis/Theora streams */
@@ -484,17 +495,22 @@
ogg_stream_init(&test,ogg_page_serialno(&og));
ogg_stream_pagein(&test,&og);
- ogg_stream_packetout(&test,&op);
+ ogg_stream_packetpeek(&test,&op);
/* identify the codec: try theora */
- if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
+ if(!theora_p && (theora_processing_headers=
+ th_decode_headerin(&ti,&tc,&ts,&op))>=0){
/* it is theora */
memcpy(&to,&test,sizeof(test));
theora_p=1;
+ /*Advance past the successfully processed header.*/
+ if(theora_processing_headers)ogg_stream_packetout(&to,NULL);
}else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
/* it is vorbis */
memcpy(&vo,&test,sizeof(test));
vorbis_p=1;
+ /*Advance past the successfully processed header.*/
+ ogg_stream_packetout(&vo,NULL);
}else{
/* whatever it is, we don't care about it */
ogg_stream_clear(&test);
@@ -504,21 +520,22 @@
}
/* we're expecting more header packets. */
- while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
+ while((theora_p && theora_processing_headers) || (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){
- fprintf(stderr,"Error parsing Theora stream headers; corrupt stream?\n");
- exit(1);
- }
- if(theora_decode_header(&ti,&tc,&op)){
+ while(theora_processing_headers&&(ret=ogg_stream_packetpeek(&to,&op))){
+ if(ret<0)continue;
+ theora_processing_headers=th_decode_headerin(&ti,&tc,&ts,&op);
+ if(theora_processing_headers<0){
printf("Error parsing Theora stream headers; corrupt stream?\n");
exit(1);
}
+ else if(theora_processing_headers>0){
+ /*Advance past the successfully processed header.*/
+ ogg_stream_packetout(&to,NULL);
+ }
theora_p++;
- if(theora_p==3)break;
}
/* look for more vorbis header packets */
@@ -535,6 +552,10 @@
if(vorbis_p==3)break;
}
+ /*Stop now so we don't fail if there aren't enough pages in a short
+ stream.*/
+ if(!(theora_p&&theora_processing_headers)&&!(vorbis_p&&vorbis_p<3))break;
+
/* The header pages/packets will arrive before anything else we
care about, or the stream is not obeying spec */
@@ -551,34 +572,32 @@
/* and now we have it all. initialize decoders */
if(theora_p){
- theora_decode_init(&td,&ti);
- printf("Ogg logical stream %x is Theora %dx%d %.02f fps",
- (unsigned int)to.serialno,ti.width,ti.height,
+ td=th_decode_alloc(&ti,ts);
+ printf("Ogg logical stream %lx is Theora %dx%d %.02f fps video\n",
+ to.serialno,ti.frame_width,ti.frame_height,
(double)ti.fps_numerator/ti.fps_denominator);
- switch(ti.pixelformat){
- case OC_PF_420: printf(" 4:2:0 video\n"); break;
- case OC_PF_422: printf(" 4:2:2 video\n"); break;
- case OC_PF_444: printf(" 4:4:4 video\n"); break;
- case OC_PF_RSVD:
- default:
- printf(" video\n (UNKNOWN Chroma sampling!)\n");
- break;
- }
- if(ti.width!=ti.frame_width || ti.height!=ti.frame_height)
+ if(ti.frame_width!=ti.pic_width || ti.frame_height!=ti.pic_height)
printf(" Frame content is %dx%d with offset (%d,%d).\n",
- ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
+ ti.pic_width, ti.pic_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;
}else{
/* tear down the partial theora setup */
- theora_info_clear(&ti);
- theora_comment_clear(&tc);
+ th_info_clear(&ti);
+ th_comment_clear(&tc);
}
+ /*Either way, we're done with the codec setup data.*/
+ th_setup_free(ts);
if(vorbis_p){
vorbis_synthesis_init(&vd,&vi);
vorbis_block_init(&vd,&vb);
- fprintf(stderr,"Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
- (unsigned int)vo.serialno,vi.channels,(int)vi.rate);
+ fprintf(stderr,"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);
@@ -644,20 +663,41 @@
/* theora is one in, one out... */
if(ogg_stream_packetout(&to,&op)>0){
- theora_decode_packetin(&td,&op);
- videobuf_granulepos=td.granulepos;
-
- videobuf_time=theora_granule_time(&td,videobuf_granulepos);
+ 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++;
- /* 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. */
+ /* 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;
-
+ 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++;
+ }
+ }
+
}else
break;
}
@@ -666,7 +706,7 @@
if(!videobuf_ready || !audiobuf_ready){
/* no data yet for somebody. Grab another page */
- int bytes=buffer_data(infile,&oy);
+ buffer_data(infile,&oy);
while(ogg_sync_pageout(&oy,&og)>0){
queue_page(&og);
}
@@ -703,7 +743,17 @@
}
if(theora_p){
- long milliseconds=(videobuf_time-get_time())*1000-5;
+ 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;
@@ -740,17 +790,21 @@
}
if(theora_p){
ogg_stream_clear(&to);
- theora_clear(&td);
- theora_comment_clear(&tc);
- theora_info_clear(&ti);
+ th_decode_free(td);
+ th_comment_clear(&tc);
+ th_info_clear(&ti);
}
ogg_sync_clear(&oy);
if(infile && infile!=stdin)fclose(infile);
fprintf(stderr,
- "\r "
- "\nDone.\n");
+ "\r \r");
+ fprintf(stderr, "%d frames", frames);
+ if (dropped) fprintf(stderr, " (%d dropped)", dropped);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "\nDone.\n");
+
return(0);
}
Modified: trunk/theora/lib/Makefile.am
===================================================================
--- trunk/theora/lib/Makefile.am 2007-04-14 07:51:10 UTC (rev 12862)
+++ trunk/theora/lib/Makefile.am 2007-04-15 09:49:31 UTC (rev 12863)
@@ -41,7 +41,6 @@
enc/mcomp.c \
enc/misc_common.c \
enc/pb.c \
- enc/pp.c \
enc/reconstruct.c \
enc/scan.c \
enc/dsp.c
@@ -114,7 +113,6 @@
enc/encoder_lookup.h \
enc/encoder_huffman.h \
enc/hufftables.h \
- enc/pp.h \
enc/quant_lookup.h \
enc/toplevel_lookup.h \
enc/dsp.h \
Deleted: trunk/theora/lib/enc/pp.c
===================================================================
--- trunk/theora/lib/enc/pp.c 2007-04-14 07:51:10 UTC (rev 12862)
+++ trunk/theora/lib/enc/pp.c 2007-04-15 09:49:31 UTC (rev 12863)
@@ -1,954 +0,0 @@
-/********************************************************************
- * *
- * 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-2003 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************
-
- function:
- last mod: $Id$
-
- ********************************************************************/
-
-#include <stdlib.h>
-#include <string.h>
-#include "codec_internal.h"
-#include "pp.h"
-#include "dsp.h"
-
-#define MAX(a, b) ((a>b)?a:b)
-#define MIN(a, b) ((a<b)?a:b)
-#define PP_QUALITY_THRESH 49
-
-static const ogg_int32_t SharpenModifier[ Q_TABLE_SIZE ] =
-{ -12, -11, -10, -10, -9, -9, -9, -9,
- -6, -6, -6, -6, -6, -6, -6, -6,
- -4, -4, -4, -4, -4, -4, -4, -4,
- -2, -2, -2, -2, -2, -2, -2, -2,
- -2, -2, -2, -2, -2, -2, -2, -2,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const ogg_uint32_t DcQuantScaleV1[ Q_TABLE_SIZE ] = {
- 22, 20, 19, 18, 17, 17, 16, 16,
- 15, 15, 14, 14, 13, 13, 12, 12,
- 11, 11, 10, 10, 9, 9, 9, 8,
- 8, 8, 7, 7, 7, 6, 6, 6,
- 6, 5, 5, 5, 5, 4, 4, 4,
- 4, 4, 3, 3, 3, 3, 3, 3,
- 3, 2, 2, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1
-};
-
-static const ogg_uint32_t * const DeringModifierV1=DcQuantScaleV1;
-
-static void PClearFrameInfo(PP_INSTANCE * ppi){
- int i;
-
- if(ppi->ScanPixelIndexTable) _ogg_free(ppi->ScanPixelIndexTable);
- ppi->ScanPixelIndexTable=0;
-
- if(ppi->ScanDisplayFragments) _ogg_free(ppi->ScanDisplayFragments);
- ppi->ScanDisplayFragments=0;
-
- for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
- if(ppi->PrevFragments[i]){
- _ogg_free(ppi->PrevFragments[i]);
- ppi->PrevFragments[i]=0;
- }
-
- if(ppi->FragScores) _ogg_free(ppi->FragScores);
- ppi->FragScores=0;
-
- if(ppi->SameGreyDirPixels) _ogg_free(ppi->SameGreyDirPixels);
- ppi->SameGreyDirPixels=0;
-
- if(ppi->FragDiffPixels) _ogg_free(ppi->FragDiffPixels);
- ppi->FragDiffPixels=0;
-
- if(ppi->BarBlockMap) _ogg_free(ppi->BarBlockMap);
- ppi->BarBlockMap=0;
-
- if(ppi->TmpCodedMap) _ogg_free(ppi->TmpCodedMap);
- ppi->TmpCodedMap=0;
-
- if(ppi->RowChangedPixels) _ogg_free(ppi->RowChangedPixels);
- ppi->RowChangedPixels=0;
-
- if(ppi->PixelScores) _ogg_free(ppi->PixelScores);
- ppi->PixelScores=0;
-
- if(ppi->PixelChangedMap) _ogg_free(ppi->PixelChangedMap);
- ppi->PixelChangedMap=0;
-
- if(ppi->ChLocals) _ogg_free(ppi->ChLocals);
- ppi->ChLocals=0;
-
- if(ppi->yuv_differences) _ogg_free(ppi->yuv_differences);
- ppi->yuv_differences=0;
-
-}
-
-void PInitFrameInfo(PP_INSTANCE * ppi){
- int i;
- PClearFrameInfo(ppi);
-
- ppi->ScanPixelIndexTable =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanPixelIndexTable));
-
- ppi->ScanDisplayFragments =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->ScanDisplayFragments));
-
- for(i = 0 ; i < MAX_PREV_FRAMES ; i ++)
- ppi->PrevFragments[i] =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->PrevFragments));
-
- ppi->FragScores =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
-
- ppi->SameGreyDirPixels =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->SameGreyDirPixels));
-
- ppi->FragDiffPixels =
- _ogg_malloc(ppi->ScanFrameFragments*sizeof(*ppi->FragScores));
-
- ppi->BarBlockMap=
- _ogg_malloc(3 * ppi->ScanHFragments*sizeof(*ppi->BarBlockMap));
-
- ppi->TmpCodedMap =
- _ogg_malloc(ppi->ScanHFragments*sizeof(*ppi->TmpCodedMap));
-
- ppi->RowChangedPixels =
- _ogg_malloc(3 * ppi->ScanConfig.VideoFrameHeight*
- sizeof(*ppi->RowChangedPixels));
-
- ppi->PixelScores =
- _ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
- sizeof(*ppi->PixelScores) * PSCORE_CB_ROWS);
-
- ppi->PixelChangedMap =
- _ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
- sizeof(*ppi->PixelChangedMap) * PMAP_CB_ROWS);
-
- ppi->ChLocals =
- _ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
- sizeof(*ppi->ChLocals) * CHLOCALS_CB_ROWS);
-
- ppi->yuv_differences =
- _ogg_malloc(ppi->ScanConfig.VideoFrameWidth*
- sizeof(*ppi->yuv_differences) * YDIFF_CB_ROWS);
-}
-
-void ClearPPInstance(PP_INSTANCE *ppi){
- PClearFrameInfo(ppi);
-}
-
-
-void InitPPInstance(PP_INSTANCE *ppi, DspFunctions *funcs){
-
- memset(ppi,0,sizeof(*ppi));
-
- memcpy(&ppi->dsp, funcs, sizeof(DspFunctions));
-
- /* Initializations */
- ppi->PrevFrameLimit = 3; /* Must not exceed MAX_PREV_FRAMES (Note
- that this number includes the current
- frame so "1 = no effect") */
-
- /* Scan control variables. */
- ppi->HFragPixels = 8;
- ppi->VFragPixels = 8;
-
- ppi->SRFGreyThresh = 4;
- ppi->SRFColThresh = 5;
- ppi->NoiseSupLevel = 3;
- ppi->SgcLevelThresh = 3;
- ppi->SuvcLevelThresh = 4;
-
- /* Variables controlling S.A.D. breakouts. */
- ppi->GrpLowSadThresh = 10;
- ppi->GrpHighSadThresh = 64;
- ppi->PrimaryBlockThreshold = 5;
- ppi->SgcThresh = 16; /* (Default values for 8x8 blocks). */
-
- ppi->UVBlockThreshCorrection = 1.25;
- ppi->UVSgcCorrection = 1.5;
-
- ppi->MaxLineSearchLen = MAX_SEARCH_LINE_LEN;
-}
-
-static void DeringBlockStrong(unsigned char *SrcPtr,
- unsigned char *DstPtr,
- ogg_int32_t Pitch,
- ogg_uint32_t FragQIndex,
- const ogg_uint32_t *QuantScale){
-
- ogg_int16_t UDMod[72];
- ogg_int16_t LRMod[72];
- unsigned int j,k,l;
- const unsigned char * Src;
- unsigned int QValue = QuantScale[FragQIndex];
-
- unsigned char p;
- unsigned char pl;
- unsigned char pr;
- unsigned char pu;
- unsigned char pd;
-
- int al;
- int ar;
- int au;
- int ad;
-
- int atot;
- int B;
- int newVal;
-
- const unsigned char *curRow = SrcPtr - 1; /* avoid negative array indexes */
- unsigned char *dstRow = DstPtr;
- const unsigned char *lastRow = SrcPtr-Pitch;
- const unsigned char *nextRow = SrcPtr+Pitch;
-
- unsigned int rowOffset = 0;
- unsigned int round = (1<<6);
-
- int High;
- int Low;
- int TmpMod;
-
- int Sharpen = SharpenModifier[FragQIndex];
- High = 3 * QValue;
- if(High>32)High=32;
- Low = 0;
-
-
- /* Initialize the Mod Data */
- Src = SrcPtr-Pitch;
- for(k=0;k<9;k++){
- for(j=0;j<8;j++){
-
- TmpMod = 32 + QValue - (abs(Src[j+Pitch]-Src[j]));
-
- if(TmpMod< -64)
- TmpMod = Sharpen;
-
- else if(TmpMod<Low)
- TmpMod = Low;
-
- else if(TmpMod>High)
- TmpMod = High;
-
- UDMod[k*8+j] = (ogg_int16_t)TmpMod;
- }
- Src +=Pitch;
- }
-
- Src = SrcPtr-1;
-
- for(k=0;k<8;k++){
- for(j=0;j<9;j++){
- TmpMod = 32 + QValue - (abs(Src[j+1]-Src[j]));
-
- if(TmpMod< -64 )
- TmpMod = Sharpen;
-
- else if(TmpMod<0)
- TmpMod = Low;
-
- else if(TmpMod>High)
- TmpMod = High;
-
- LRMod[k*9+j] = (ogg_int16_t)TmpMod;
- }
- Src+=Pitch;
- }
-
- for(k=0;k<8;k++){
- /* In the case that this function called with same buffer for
- source and destination, To keep the c and the mmx version to have
- consistant results, intermediate buffer is used to store the
- eight pixel value before writing them to destination
- (i.e. Overwriting souce for the speical case) */
- for(l=0;l<8;l++){
-
- atot = 128;
- B = round;
- p = curRow[ rowOffset +l +1];
-
- pl = curRow[ rowOffset +l];
- al = LRMod[k*9+l];
- atot -= al;
- B += al * pl;
-
- pu = lastRow[ rowOffset +l];
- au = UDMod[k*8+l];
- atot -= au;
- B += au * pu;
-
- pd = nextRow[ rowOffset +l];
- ad = UDMod[(k+1)*8+l];
- atot -= ad;
- B += ad * pd;
-
- pr = curRow[ rowOffset +l+2];
- ar = LRMod[k*9+l+1];
- atot -= ar;
- B += ar * pr;
-
- newVal = ( atot * p + B) >> 7;
-
- dstRow[ rowOffset +l]= clamp255( newVal );
- }
- rowOffset += Pitch;
- }
-}
-
-static void DeringBlockWeak(unsigned char *SrcPtr,
- unsigned char *DstPtr,
- ogg_int32_t Pitch,
- ogg_uint32_t FragQIndex,
- const ogg_uint32_t *QuantScale){
-
- ogg_int16_t UDMod[72];
- ogg_int16_t LRMod[72];
- unsigned int j,k;
- const unsigned char * Src;
- unsigned int QValue = QuantScale[FragQIndex];
-
- unsigned char p;
- unsigned char pl;
- unsigned char pr;
- unsigned char pu;
- unsigned char pd;
-
- int al;
- int ar;
- int au;
- int ad;
-
- int atot;
- int B;
- int newVal;
-
- const unsigned char *curRow = SrcPtr-1;
- unsigned char *dstRow = DstPtr;
- const unsigned char *lastRow = SrcPtr-Pitch;
- const unsigned char *nextRow = SrcPtr+Pitch;
-
- unsigned int rowOffset = 0;
- unsigned int round = (1<<6);
-
- int High;
- int Low;
- int TmpMod;
- int Sharpen = SharpenModifier[FragQIndex];
-
- High = 3 * QValue;
- if(High>24)
- High=24;
- Low = 0 ;
-
- /* Initialize the Mod Data */
- Src=SrcPtr-Pitch;
- for(k=0;k<9;k++) {
- for(j=0;j<8;j++) {
-
- TmpMod = 32 + QValue - 2*(abs(Src[j+Pitch]-Src[j]));
-
- if(TmpMod< -64)
- TmpMod = Sharpen;
-
- else if(TmpMod<Low)
- TmpMod = Low;
-
- else if(TmpMod>High)
- TmpMod = High;
-
- UDMod[k*8+j] = (ogg_int16_t)TmpMod;
- }
- Src +=Pitch;
- }
-
- Src = SrcPtr-1;
-
- for(k=0;k<8;k++){
- for(j=0;j<9;j++){
- TmpMod = 32 + QValue - 2*(abs(Src[j+1]-Src[j]));
-
- if(TmpMod< -64 )
- TmpMod = Sharpen;
-
- else if(TmpMod<Low)
- TmpMod = Low;
-
- else if(TmpMod>High)
- TmpMod = High;
-
- LRMod[k*9+j] = (ogg_int16_t)TmpMod;
- }
- Src+=Pitch;
- }
-
- for(k=0;k<8;k++) {
- for(j=0;j<8;j++){
- atot = 128;
- B = round;
- p = curRow[ rowOffset +j+1];
-
- pl = curRow[ rowOffset +j];
- al = LRMod[k*9+j];
- atot -= al;
- B += al * pl;
-
- pu = lastRow[ rowOffset +j];
- au = UDMod[k*8+j];
- atot -= au;
- B += au * pu;
-
- pd = nextRow[ rowOffset +j];
- ad = UDMod[(k+1)*8+j];
- atot -= ad;
- B += ad * pd;
-
- pr = curRow[ rowOffset +j+2];
- ar = LRMod[k*9+j+1];
- atot -= ar;
- B += ar * pr;
-
- newVal = ( atot * p + B) >> 7;
-
- dstRow[ rowOffset +j] = clamp255( newVal );
- }
-
- rowOffset += Pitch;
- }
-}
-
-static void DeringFrame(PB_INSTANCE *pbi,
- unsigned char *Src, unsigned char *Dst){
- ogg_uint32_t col,row;
- unsigned char *SrcPtr;
- unsigned char *DestPtr;
- ogg_uint32_t BlocksAcross,BlocksDown;
- const ogg_uint32_t *QuantScale;
- ogg_uint32_t Block;
- ogg_uint32_t LineLength;
-
- ogg_int32_t Thresh1,Thresh2,Thresh3,Thresh4;
-
- Thresh1 = 384;
- Thresh2 = 4 * Thresh1;
- Thresh3 = 5 * Thresh2/4;
- Thresh4 = 5 * Thresh2/2;
-
- QuantScale = DeringModifierV1;
-
- BlocksAcross = pbi->HFragments;
- BlocksDown = pbi->VFragments;
-
- SrcPtr = Src + pbi->ReconYDataOffset;
- DestPtr = Dst + pbi->ReconYDataOffset;
- LineLength = pbi->YStride;
-
- Block = 0;
-
- for ( row = 0 ; row < BlocksDown; row ++){
- for (col = 0; col < BlocksAcross; col ++){
- ogg_uint32_t Quality = pbi->FragQIndex[Block];
- ogg_int32_t Variance = pbi->FragmentVariances[Block];
-
- if( pbi->PostProcessingLevel >5 && Variance > Thresh3 ){
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
-
- if( (col > 0 &&
- pbi->FragmentVariances[Block-1] > Thresh4 ) ||
- (col + 1 < BlocksAcross &&
- pbi->FragmentVariances[Block+1] > Thresh4 ) ||
- (row + 1 < BlocksDown &&
- pbi->FragmentVariances[Block+BlocksAcross] > Thresh4) ||
- (row > 0 &&
- pbi->FragmentVariances[Block-BlocksAcross] > Thresh4) ){
-
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- }
- } else if(Variance > Thresh2 ) {
-
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- } else if(Variance > Thresh1 ) {
-
- DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
-
- } else {
-
- dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
-
- }
-
- ++Block;
-
- }
- SrcPtr += 8 * LineLength;
- DestPtr += 8 * LineLength;
- }
-
- /* Then U */
-
- BlocksAcross /= 2;
- BlocksDown /= 2;
- LineLength /= 2;
-
- SrcPtr = Src + pbi->ReconUDataOffset;
- DestPtr = Dst + pbi->ReconUDataOffset;
- for ( row = 0 ; row < BlocksDown; row ++) {
- for (col = 0; col < BlocksAcross; col ++) {
- ogg_uint32_t Quality = pbi->FragQIndex[Block];
- ogg_int32_t Variance = pbi->FragmentVariances[Block];
-
- if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) {
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
-
- }else if(Variance > Thresh2 ){
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- }else if(Variance > Thresh1 ){
- DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- }else{
- dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
- }
-
- ++Block;
-
- }
- SrcPtr += 8 * LineLength;
- DestPtr += 8 * LineLength;
- }
-
- /* Then V */
- SrcPtr = Src + pbi->ReconVDataOffset;
- DestPtr = Dst + pbi->ReconVDataOffset;
-
- for ( row = 0 ; row < BlocksDown; row ++){
- for (col = 0; col < BlocksAcross; col ++){
-
- ogg_uint32_t Quality = pbi->FragQIndex[Block];
- ogg_int32_t Variance = pbi->FragmentVariances[Block];
-
-
- if( pbi->PostProcessingLevel >5 && Variance > Thresh4 ) {
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
-
- }else if(Variance > Thresh2 ){
- DeringBlockStrong(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- }else if(Variance > Thresh1 ){
- DeringBlockWeak(SrcPtr + 8 * col, DestPtr + 8 * col,
- LineLength,Quality,QuantScale);
- }else{
- dsp_copy8x8(pbi->dsp, SrcPtr + 8 * col, DestPtr + 8 * col, LineLength);
- }
-
- ++Block;
-
- }
- SrcPtr += 8 * LineLength;
- DestPtr += 8 * LineLength;
-
- }
-
-}
-
-void UpdateFragQIndex(PB_INSTANCE *pbi){
-
- ogg_uint32_t ThisFrameQIndex;
- ogg_uint32_t i;
-
- /* Check this frame quality index */
- ThisFrameQIndex = pbi->FrameQIndex;
-
-
- /* It is not a key frame, so only reset those are coded */
- for( i = 0; i < pbi->UnitFragments; i++ )
- if( pbi->display_fragments[i])
- pbi->FragQIndex[i] = ThisFrameQIndex;
-
-}
-
-static void DeblockLoopFilteredBand(PB_INSTANCE *pbi,
- unsigned char *SrcPtr,
- unsigned char *DesPtr,
- ogg_uint32_t PlaneLineStep,
- ogg_uint32_t FragsAcross,
- ogg_uint32_t StartFrag,
- const ogg_uint32_t *QuantScale){
- ogg_uint32_t j,k;
- ogg_uint32_t CurrentFrag=StartFrag;
- ogg_int32_t QStep;
- ogg_int32_t FLimit;
- unsigned char *Src, *Des;
- ogg_int32_t x[10];
- ogg_int32_t Sum1, Sum2;
-
- while(CurrentFrag < StartFrag + FragsAcross){
-
- Src=SrcPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*5;
- Des=DesPtr+8*(CurrentFrag-StartFrag)-PlaneLineStep*4;
-
- QStep = QuantScale[pbi->FragQIndex[CurrentFrag+FragsAcross]];
- FLimit = ( QStep * 3 ) >> 2;
-
- for( j=0; j<8 ; j++){
- x[0] = Src[0];
- x[1] = Src[PlaneLineStep];
- x[2] = Src[PlaneLineStep*2];
- x[3] = Src[PlaneLineStep*3];
- x[4] = Src[PlaneLineStep*4];
- x[5] = Src[PlaneLineStep*5];
- x[6] = Src[PlaneLineStep*6];
- x[7] = Src[PlaneLineStep*7];
- x[8] = Src[PlaneLineStep*8];
- x[9] = Src[PlaneLineStep*9];
-
- Sum1=Sum2=0;
-
- for(k=1;k<=4;k++){
- Sum1 += abs(x[k]-x[k-1]);
- Sum2 += abs(x[k+4]-x[k+5]);
- }
-
- pbi->FragmentVariances[CurrentFrag] +=((Sum1>255)?255:Sum1);
- pbi->FragmentVariances[CurrentFrag + FragsAcross] += ((Sum2>255)?255:Sum2);
-
- if( Sum1 < FLimit &&
- Sum2 < FLimit &&
- (x[5] - x[4]) < QStep &&
- (x[4] - x[5]) < QStep ){
-
- /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
- Des[0 ] = (x[0] + x[0] +x[0] + x[1] * 2 +
- x[2] + x[3] +x[4] + 4) >> 3;
- Des[PlaneLineStep ] = (x[0] + x[0] +x[1] + x[2] * 2 +
- x[3] + x[4] +x[5] + 4) >> 3;
- Des[PlaneLineStep*2] = (x[0] + x[1] +x[2] + x[3] * 2 +
- x[4] + x[5] +x[6] + 4) >> 3;
- Des[PlaneLineStep*3] = (x[1] + x[2] +x[3] + x[4] * 2 +
- x[5] + x[6] +x[7] + 4) >> 3;
- Des[PlaneLineStep*4] = (x[2] + x[3] +x[4] + x[5] * 2 +
- x[6] + x[7] +x[8] + 4) >> 3;
- Des[PlaneLineStep*5] = (x[3] + x[4] +x[5] + x[6] * 2 +
- x[7] + x[8] +x[9] + 4) >> 3;
- Des[PlaneLineStep*6] = (x[4] + x[5] +x[6] + x[7] * 2 +
- x[8] + x[9] +x[9] + 4) >> 3;
- Des[PlaneLineStep*7] = (x[5] + x[6] +x[7] + x[8] * 2 +
- x[9] + x[9] +x[9] + 4) >> 3;
-
- }else {
- /* copy the pixels to destination */
- Des[0 ]= (unsigned char)x[1];
- Des[PlaneLineStep ]= (unsigned char)x[2];
- Des[PlaneLineStep*2]= (unsigned char)x[3];
- Des[PlaneLineStep*3]= (unsigned char)x[4];
- Des[PlaneLineStep*4]= (unsigned char)x[5];
- Des[PlaneLineStep*5]= (unsigned char)x[6];
- Des[PlaneLineStep*6]= (unsigned char)x[7];
- Des[PlaneLineStep*7]= (unsigned char)x[8];
- }
- Src ++;
- Des ++;
- }
-
-
- /* done with filtering the horizontal edge, now let's do the
- vertical one */
- /* skip the first one */
- if(CurrentFrag==StartFrag)
- CurrentFrag++;
- else{
- Des=DesPtr-8*PlaneLineStep+8*(CurrentFrag-StartFrag);
- Src=Des-5;
- Des-=4;
-
- QStep = QuantScale[pbi->FragQIndex[CurrentFrag]];
- FLimit = ( QStep * 3 ) >> 2;
-
- for( j=0; j<8 ; j++){
- x[0] = Src[0];
- x[1] = Src[1];
- x[2] = Src[2];
- x[3] = Src[3];
- x[4] = Src[4];
- x[5] = Src[5];
- x[6] = Src[6];
- x[7] = Src[7];
- x[8] = Src[8];
- x[9] = Src[9];
-
- Sum1=Sum2=0;
-
- for(k=1;k<=4;k++){
- Sum1 += abs(x[k]-x[k-1]);
- Sum2 += abs(x[k+4]-x[k+5]);
- }
-
- pbi->FragmentVariances[CurrentFrag-1] += ((Sum1>255)?255:Sum1);
- pbi->FragmentVariances[CurrentFrag] += ((Sum2>255)?255:Sum2);
-
- if( Sum1 < FLimit &&
- Sum2 < FLimit &&
- (x[5] - x[4]) < QStep &&
- (x[4] - x[5]) < QStep ){
-
- /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
- Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3;
- Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3;
- Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3;
- Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3;
- Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3;
- Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3;
- Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3;
- Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3;
- }
-
- Src += PlaneLineStep;
- Des += PlaneLineStep;
- }
- CurrentFrag ++;
- }
- }
-}
-
-static void DeblockVerticalEdgesInLoopFilteredBand(PB_INSTANCE *pbi,
- unsigned char *SrcPtr,
- unsigned char *DesPtr,
- ogg_uint32_t PlaneLineStep,
- ogg_uint32_t FragsAcross,
- ogg_uint32_t StartFrag,
- const ogg_uint32_t *QuantScale){
- ogg_uint32_t j,k;
- ogg_uint32_t CurrentFrag=StartFrag;
- ogg_int32_t QStep;
- ogg_int32_t FLimit;
- unsigned char *Src, *Des;
- ogg_int32_t x[10];
- ogg_int32_t Sum1, Sum2;
-
- while(CurrentFrag < StartFrag + FragsAcross-1) {
-
- Src=SrcPtr+8*(CurrentFrag-StartFrag+1)-5;
- Des=DesPtr+8*(CurrentFrag-StartFrag+1)-4;
-
- QStep = QuantScale[pbi->FragQIndex[CurrentFrag+1]];
- FLimit = ( QStep * 3)>>2 ;
-
- for( j=0; j<8 ; j++){
- x[0] = Src[0];
- x[1] = Src[1];
- x[2] = Src[2];
- x[3] = Src[3];
- x[4] = Src[4];
- x[5] = Src[5];
- x[6] = Src[6];
- x[7] = Src[7];
- x[8] = Src[8];
- x[9] = Src[9];
-
- Sum1=Sum2=0;
-
- for(k=1;k<=4;k++){
- Sum1 += abs(x[k]-x[k-1]);
- Sum2 += abs(x[k+4]-x[k+5]);
- }
-
- pbi->FragmentVariances[CurrentFrag] += ((Sum1>255)?255:Sum1);
- pbi->FragmentVariances[CurrentFrag+1] += ((Sum2>255)?255:Sum2);
-
-
- if( Sum1 < FLimit &&
- Sum2 < FLimit &&
- (x[5] - x[4]) < QStep &&
- (x[4] - x[5]) < QStep ){
-
- /* low pass filtering (LPF7: 1 1 1 2 1 1 1) */
- Des[0] = (x[0] + x[0] +x[0] + x[1] * 2 + x[2] + x[3] +x[4] + 4) >> 3;
- Des[1] = (x[0] + x[0] +x[1] + x[2] * 2 + x[3] + x[4] +x[5] + 4) >> 3;
- Des[2] = (x[0] + x[1] +x[2] + x[3] * 2 + x[4] + x[5] +x[6] + 4) >> 3;
- Des[3] = (x[1] + x[2] +x[3] + x[4] * 2 + x[5] + x[6] +x[7] + 4) >> 3;
- Des[4] = (x[2] + x[3] +x[4] + x[5] * 2 + x[6] + x[7] +x[8] + 4) >> 3;
- Des[5] = (x[3] + x[4] +x[5] + x[6] * 2 + x[7] + x[8] +x[9] + 4) >> 3;
- Des[6] = (x[4] + x[5] +x[6] + x[7] * 2 + x[8] + x[9] +x[9] + 4) >> 3;
- Des[7] = (x[5] + x[6] +x[7] + x[8] * 2 + x[9] + x[9] +x[9] + 4) >> 3;
- }
- Src +=PlaneLineStep;
- Des +=PlaneLineStep;
-
- }
- CurrentFrag ++;
- }
-}
-
-static void DeblockPlane(PB_INSTANCE *pbi,
- unsigned char *SourceBuffer,
- unsigned char *DestinationBuffer,
- ogg_uint32_t Channel ){
-
- ogg_uint32_t i,k;
- ogg_uint32_t PlaneLineStep=0;
- ogg_uint32_t StartFrag =0;
- ogg_uint32_t PixelIndex=0;
- unsigned char * SrcPtr=0, * DesPtr=0;
- ogg_uint32_t FragsAcross=0;
- ogg_uint32_t FragsDown=0;
- const ogg_uint32_t *QuantScale=0;
-
- switch( Channel ){
- case 0:
- /* Get the parameters */
- PlaneLineStep = pbi->YStride;
- FragsAcross = pbi->HFragments;
- FragsDown = pbi->VFragments;
- StartFrag = 0;
- PixelIndex = pbi->ReconYDataOffset;
- SrcPtr = & SourceBuffer[PixelIndex];
- DesPtr = & DestinationBuffer[PixelIndex];
- break;
-
- case 1:
- /* Get the parameters */
- PlaneLineStep = pbi->UVStride;
- FragsAcross = pbi->HFragments / 2;
- FragsDown = pbi->VFragments / 2;
- StartFrag = pbi->YPlaneFragments;
-
- PixelIndex = pbi->ReconUDataOffset;
- SrcPtr = & SourceBuffer[PixelIndex];
- DesPtr = & DestinationBuffer[PixelIndex];
- break;
-
- default:
- /* Get the parameters */
- PlaneLineStep = pbi->UVStride;
- FragsAcross = pbi->HFragments / 2;
- FragsDown = pbi->VFragments / 2;
- StartFrag = pbi->YPlaneFragments + pbi->UVPlaneFragments;
-
- PixelIndex = pbi->ReconVDataOffset;
- SrcPtr = & SourceBuffer[PixelIndex];
- DesPtr = & DestinationBuffer[PixelIndex];
- break;
- }
-
- QuantScale = DcQuantScaleV1;
-
- for(i=0;i<4;i++)
- memcpy(DesPtr+i*PlaneLineStep, SrcPtr+i*PlaneLineStep, PlaneLineStep);
-
- k = 1;
-
- while( k < FragsDown ){
-
- SrcPtr += 8*PlaneLineStep;
- DesPtr += 8*PlaneLineStep;
-
- /* Filter both the horizontal and vertical block edges inside the band */
- DeblockLoopFilteredBand(pbi, SrcPtr, DesPtr, PlaneLineStep,
- FragsAcross, StartFrag, QuantScale);
-
- /* Move Pointers */
- StartFrag += FragsAcross;
-
- k ++;
- }
-
- /* The Last band */
- for(i=0;i<4;i++)
- memcpy(DesPtr+(i+4)*PlaneLineStep,
- SrcPtr+(i+4)*PlaneLineStep,
- PlaneLineStep);
-
- DeblockVerticalEdgesInLoopFilteredBand(pbi,SrcPtr,DesPtr,PlaneLineStep,
- FragsAcross,StartFrag,QuantScale);
-
-}
-
-static void DeblockFrame(PB_INSTANCE *pbi, unsigned char *SourceBuffer,
- unsigned char *DestinationBuffer){
-
- memset(pbi->FragmentVariances, 0 , sizeof(ogg_int32_t) * pbi->UnitFragments);
-
-
- UpdateFragQIndex(pbi);
-
-
- SetupLoopFilter(pbi);
-
- /* Y */
- DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 0);
-
- /* U */
- DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 1);
-
- /* V */
- DeblockPlane( pbi, SourceBuffer, DestinationBuffer, 2);
-
-}
-
-void PostProcess(PB_INSTANCE *pbi){
-
- switch (pbi->PostProcessingLevel){
- case 8:
- /* on a slow machine, use a simpler and faster deblocking filter */
- DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
- break;
-
- case 6:
- DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
- UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
- DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
- break;
-
- case 5:
- DeblockFrame(pbi, pbi->LastFrameRecon,pbi->PostProcessBuffer);
- UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
- DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
- break;
- case 4:
- DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer);
- break;
- case 1:
- UpdateFragQIndex(pbi);
- break;
-
- case 0:
- break;
-
- default:
- DeblockFrame(pbi, pbi->LastFrameRecon, pbi->PostProcessBuffer);
- UpdateUMVBorder(pbi, pbi->PostProcessBuffer );
- DeringFrame(pbi, pbi->PostProcessBuffer, pbi->PostProcessBuffer);
- break;
- }
-}
-
Deleted: trunk/theora/lib/enc/pp.h
===================================================================
--- trunk/theora/lib/enc/pp.h 2007-04-14 07:51:10 UTC (rev 12862)
+++ trunk/theora/lib/enc/pp.h 2007-04-15 09:49:31 UTC (rev 12863)
@@ -1,48 +0,0 @@
-/********************************************************************
- * *
- * 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-2003 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************
-
- function:
- last mod: $Id$
-
- ********************************************************************/
-
-/* Constants. */
-#define INTERNAL_BLOCK_HEIGHT 8
-#define INTERNAL_BLOCK_WIDTH 8
-
-
-/* NEW Line search values. */
-#define UP 0
-#define DOWN 1
-#define LEFT 2
-#define RIGHT 3
-
-#define FIRST_ROW 0
-#define NOT_EDGE_ROW 1
-#define LAST_ROW 2
-
-#define YDIFF_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
-#define CHLOCALS_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
-#define PMAP_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 3)
-#define PSCORE_CB_ROWS (INTERNAL_BLOCK_HEIGHT * 4)
-
-/* Status values in block coding map */
-#define CANDIDATE_BLOCK_LOW -2
-#define CANDIDATE_BLOCK -1
-#define BLOCK_NOT_CODED 0
-#define BLOCK_CODED_BAR 3
-#define BLOCK_CODED_SGC 4
-#define BLOCK_CODED_LOW 4
-#define BLOCK_CODED 5
-
-#define MAX_PREV_FRAMES 16
-#define MAX_SEARCH_LINE_LEN 7
More information about the commits
mailing list