diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/video_out/deinterlace.c | 254 | ||||
-rw-r--r-- | src/video_out/deinterlace.h | 4 | ||||
-rw-r--r-- | src/video_out/video_out_xv.c | 100 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 14 |
4 files changed, 308 insertions, 64 deletions
diff --git a/src/video_out/deinterlace.c b/src/video_out/deinterlace.c index 13217b111..67f932612 100644 --- a/src/video_out/deinterlace.c +++ b/src/video_out/deinterlace.c @@ -30,6 +30,7 @@ #include "cpu_accel.h" #include "deinterlace.h" + /* DeinterlaceFieldBob algorithm Based on Virtual Dub plugin by Gunnar Thalin @@ -37,30 +38,30 @@ Linux version for Xine player by Miguel Freitas Todo: use a MMX optimized memcpy */ -static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc, +static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], int width, int height ) { #ifdef ARCH_X86 int Line; - long long* YVal1; - long long* YVal2; - long long* YVal3; - long long* Dest; - uint8_t* pEvenLines = psrc; - uint8_t* pOddLines = psrc+width; + uint64_t *YVal1; + uint64_t *YVal2; + uint64_t *YVal3; + uint64_t *Dest; + uint8_t* pEvenLines = psrc[0]; + uint8_t* pOddLines = psrc[0]+width; int LineLength = width; - int Pitch = width * 2; + int SourcePitch = width * 2; int IsOdd = 1; long EdgeDetect = 625; long JaggieThreshold = 73; int n; - unsigned long long qwEdgeDetect; - unsigned long long qwThreshold; - const unsigned long long Mask = 0xfefefefefefefefe; - const unsigned long long YMask = 0x00ff00ff00ff00ff; + uint64_t qwEdgeDetect; + uint64_t qwThreshold; + const uint64_t Mask = 0xfefefefefefefefe; + const uint64_t YMask = 0x00ff00ff00ff00ff; qwEdgeDetect = EdgeDetect; qwEdgeDetect += (qwEdgeDetect << 48) + (qwEdgeDetect << 32) + (qwEdgeDetect << 16); @@ -79,17 +80,17 @@ static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc, { if (IsOdd) { - YVal1 = (long long *)(pOddLines + Line * Pitch); - YVal2 = (long long *)(pEvenLines + (Line + 1) * Pitch); - YVal3 = (long long *)(pOddLines + (Line + 1) * Pitch); - Dest = (long long *)(pdst + (Line * 2 + 2) * LineLength); + YVal1 = (uint64_t *)(pOddLines + Line * SourcePitch); + YVal2 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch); + YVal3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch); + Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength); } else { - YVal1 = (long long *)(pEvenLines + Line * Pitch); - YVal2 = (long long *)(pOddLines + Line * Pitch); - YVal3 = (long long *)(pEvenLines + (Line + 1) * Pitch); - Dest = (long long *)(pdst + (Line * 2 + 1) * LineLength); + YVal1 = (uint64_t *)(pEvenLines + Line * SourcePitch); + YVal2 = (uint64_t *)(pOddLines + Line * SourcePitch); + YVal3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch); + Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength); } // For ease of reading, the comments below assume that we're operating on an odd @@ -167,7 +168,7 @@ static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc, if (! IsOdd) { memcpy(pdst + (height * 2 - 1) * LineLength, - pOddLines + (height - 1) * Pitch, + pOddLines + (height - 1) * SourcePitch, LineLength); } @@ -177,6 +178,193 @@ static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc, #endif } +/* Deinterlace the latest field, with a tendency to weave rather than bob. + Good for high detail on low-movement scenes. + NOT FINISHED! WEIRD OUTPUT!!! +*/ +static int deinterlace_weave_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], + int width, int height ) +{ +#ifdef ARCH_X86 + + int Line; + uint64_t *YVal1; + uint64_t *YVal2; + uint64_t *YVal3; + uint64_t *YVal4; + uint64_t *Dest; + uint8_t* pEvenLines = psrc[0]; + uint8_t* pOddLines = psrc[0]+width; + uint8_t* pPrevLines; + + int LineLength = width; + int SourcePitch = width * 2; + int IsOdd = 1; + + long TemporalTolerance = 300; + long SpatialTolerance = 600; + long SimilarityThreshold = 25; + + const uint64_t YMask = 0x00ff00ff00ff00ff; + + int n; + + uint64_t qwSpatialTolerance; + uint64_t qwTemporalTolerance; + uint64_t qwThreshold; + const uint64_t Mask = 0xfefefefefefefefe; + + + // Make sure we have all the data we need. + if ( psrc[0] == NULL || psrc[1] == NULL ) + return 0; + + if (IsOdd) + pPrevLines = psrc[1] + width; + else + pPrevLines = psrc[1]; + + // Since the code uses MMX to process 4 pixels at a time, we need our constants + // to be represented 4 times per quadword. + qwSpatialTolerance = SpatialTolerance; + qwSpatialTolerance += (qwSpatialTolerance << 48) + (qwSpatialTolerance << 32) + (qwSpatialTolerance << 16); + qwTemporalTolerance = TemporalTolerance; + qwTemporalTolerance += (qwTemporalTolerance << 48) + (qwTemporalTolerance << 32) + (qwTemporalTolerance << 16); + qwThreshold = SimilarityThreshold; + qwThreshold += (qwThreshold << 48) + (qwThreshold << 32) + (qwThreshold << 16); + + // copy first even line no matter what, and the first odd line if we're + // processing an even field. + memcpy(pdst, pEvenLines, LineLength); + if (!IsOdd) + memcpy(pdst + LineLength, pOddLines, LineLength); + + height = height / 2; + for (Line = 0; Line < height - 1; ++Line) + { + if (IsOdd) + { + YVal1 = (uint64_t *)(pEvenLines + Line * SourcePitch); + YVal2 = (uint64_t *)(pOddLines + Line * SourcePitch); + YVal3 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch); + YVal4 = (uint64_t *)(pPrevLines + Line * SourcePitch); + Dest = (uint64_t *)(pdst + (Line * 2 + 1) * LineLength); + } + else + { + YVal1 = (uint64_t *)(pOddLines + Line * SourcePitch); + YVal2 = (uint64_t *)(pEvenLines + (Line + 1) * SourcePitch); + YVal3 = (uint64_t *)(pOddLines + (Line + 1) * SourcePitch); + YVal4 = (uint64_t *)(pPrevLines + (Line + 1) * SourcePitch); + Dest = (uint64_t *)(pdst + (Line * 2 + 2) * LineLength); + } + + // For ease of reading, the comments below assume that we're operating on an odd + // field (i.e., that bIsOdd is true). The exact same processing is done when we + // operate on an even field, but the roles of the odd and even fields are reversed. + // It's just too cumbersome to explain the algorithm in terms of "the next odd + // line if we're doing an odd field, or the next even line if we're doing an + // even field" etc. So wherever you see "odd" or "even" below, keep in mind that + // half the time this function is called, those words' meanings will invert. + + // Copy the even scanline below this one to the overlay buffer, since we'll be + // adapting the current scanline to the even lines surrounding it. The scanline + // above has already been copied by the previous pass through the loop. + memcpy((char *)Dest + LineLength, YVal3, LineLength); + + n = LineLength >> 3; + while( n-- ) + { + movq_m2r ( *YVal1++, mm0 ); // mm0 = E1 + movq_m2r ( *YVal2++, mm1 ); // mm1 = O + movq_m2r ( *YVal3++, mm2 ); // mm2 = E2 + + movq_r2r ( mm0, mm3 ); // mm3 = intensity(E1) + movq_r2r ( mm1, mm4 ); // mm4 = intensity(O) + movq_r2r ( mm2, mm6 ); // mm6 = intensity(E2) + + pand_m2r ( *&YMask, mm3 ); + pand_m2r ( *&YMask, mm4 ); + pand_m2r ( *&YMask, mm6 ); + + // Average E1 and E2 for interpolated bobbing. + // leave result in mm0 + pand_m2r ( *&Mask, mm0 ); // mm0 = E1 with lower chroma bit stripped off + pand_m2r ( *&Mask, mm2 ); // mm2 = E2 with lower chroma bit stripped off + psrlw_i2r ( 01, mm0 ); // mm0 = E1 / 2 + psrlw_i2r ( 01, mm2 ); // mm2 = E2 / 2 + paddb_r2r ( mm2, mm0 ); + + // The meat of the work is done here. We want to see whether this pixel is + // close in luminosity to ANY of: its top neighbor, its bottom neighbor, + // or its predecessor. To do this without branching, we use MMX's + // saturation feature, which gives us Z(x) = x if x>=0, or 0 if x<0. + // + // The formula we're computing here is + // Z(ST - (E1 - O) ^ 2) + Z(ST - (E2 - O) ^ 2) + Z(TT - (Oold - O) ^ 2) + // where ST is spatial tolerance and TT is temporal tolerance. The idea + // is that if a pixel is similar to none of its neighbors, the resulting + // value will be pretty low, probably zero. A high value therefore indicates + // that the pixel had a similar neighbor. The pixel in the same position + // in the field before last (Oold) is considered a neighbor since we want + // to be able to display 1-pixel-high horizontal lines. + + movq_m2r ( *&qwSpatialTolerance, mm7 ); + movq_r2r ( mm3, mm5 ); // mm5 = E1 + psubsw_r2r ( mm4, mm5 ); // mm5 = E1 - O + psraw_i2r ( 1, mm5 ); + pmullw_r2r ( mm5, mm5 ); // mm5 = (E1 - O) ^ 2 + psubusw_r2r ( mm5, mm7 ); // mm7 = ST - (E1 - O) ^ 2, or 0 if that's negative + + movq_m2r ( *&qwSpatialTolerance, mm3 ); + movq_r2r ( mm6, mm5 ); // mm5 = E2 + psubsw_r2r ( mm4, mm5 ); // mm5 = E2 - O + psraw_i2r ( 1, mm5 ); + pmullw_r2r ( mm5, mm5 ); // mm5 = (E2 - O) ^ 2 + psubusw_r2r ( mm5, mm3 ); // mm0 = ST - (E2 - O) ^ 2, or 0 if that's negative + paddusw_r2r ( mm3, mm7 ); // mm7 = (ST - (E1 - O) ^ 2) + (ST - (E2 - O) ^ 2) + + movq_m2r ( *&qwTemporalTolerance, mm3 ); + movq_m2r ( *YVal4++, mm5 ); // mm5 = Oold + pand_m2r ( *&YMask, mm5 ); + psubsw_r2r ( mm4, mm5 ); // mm5 = Oold - O + psraw_i2r ( 1, mm5 ); // XXX + pmullw_r2r ( mm5, mm5 ); // mm5 = (Oold - O) ^ 2 + psubusw_r2r ( mm5, mm3 ); // mm0 = TT - (Oold - O) ^ 2, or 0 if that's negative + paddusw_r2r ( mm3, mm7 ); // mm7 = our magic number + + // Now compare the similarity totals against our threshold. The pcmpgtw + // instruction will populate the target register with a bunch of mask bits, + // filling words where the comparison is true with 1s and ones where it's + // false with 0s. A few ANDs and NOTs and an OR later, we have bobbed + // values for pixels under the similarity threshold and weaved ones for + // pixels over the threshold. + + pcmpgtw_m2r( *&qwThreshold, mm7 ); // mm7 = 0xffff where we're greater than the threshold, 0 elsewhere + movq_r2r ( mm7, mm6 ); // mm6 = 0xffff where we're greater than the threshold, 0 elsewhere + pand_r2r ( mm1, mm7 ); // mm7 = weaved data where we're greater than the threshold, 0 elsewhere + pandn_r2r ( mm0, mm6 ); // mm6 = bobbed data where we're not greater than the threshold, 0 elsewhere + por_r2r ( mm6, mm7 ); // mm7 = bobbed and weaved data + + movq_r2m ( mm7, *Dest++ ); + } + } + + // Copy last odd line if we're processing an odd field. + if (IsOdd) + { + memcpy(pdst + (height * 2 - 1) * LineLength, + pOddLines + (height - 1) * SourcePitch, + LineLength); + } + + // clear out the MMX registers ready for doing floating point + // again + emms(); + + return 1; +#endif +} static int check_for_mmx(void) { @@ -200,18 +388,34 @@ static void abort_mmx_missing(void) exit(1); } -void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc, +/* generic YUV deinterlacer + pdst -> pointer to destination bitmap + psrc -> array of pointers to source bitmaps ([0] = most recent) + width,height -> dimension for bitmaps + method -> DEINTERLACE_xxx +*/ + +void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[], int width, int height, int method ) { switch( method ) { case DEINTERLACE_NONE: - memcpy(pdst,psrc,width*height); + memcpy(pdst,psrc[0],width*height); break; case DEINTERLACE_BOB: if( check_for_mmx() ) - deinterlace_bob_yuv_mmx(pdst,psrc,width,height); + deinterlace_bob_yuv_mmx(pdst,psrc,width,height); + else /* FIXME: provide an alternative? */ + abort_mmx_missing(); + break; + case DEINTERLACE_WEAVE: + if( check_for_mmx() ) + { + if( !deinterlace_weave_yuv_mmx(pdst,psrc,width,height) ) + memcpy(pdst,psrc[0],width*height); + } else /* FIXME: provide an alternative? */ - abort_mmx_missing(); + abort_mmx_missing(); break; } } diff --git a/src/video_out/deinterlace.h b/src/video_out/deinterlace.h index fc9e69bd4..a4a3d22ae 100644 --- a/src/video_out/deinterlace.h +++ b/src/video_out/deinterlace.h @@ -29,11 +29,11 @@ #include "video_out.h" -void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc, +void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[], int width, int height, int method ); - #define DEINTERLACE_NONE 0 #define DEINTERLACE_BOB 1 +#define DEINTERLACE_WEAVE 2 #endif diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 25b8f6aa1..13951ad3c 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xv.c,v 1.59 2001/09/16 15:14:30 miguelfreitas Exp $ + * $Id: video_out_xv.c,v 1.60 2001/09/19 02:40:58 miguelfreitas Exp $ * * video_out_xv.c, X11 video extension interface for xine * @@ -27,7 +27,7 @@ * Xv image support by Gerd Knorr <kraxel@goldbach.in-berlin.de> * * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de> - * + * * overlay support by James Courtier-Dutton <James@superbug.demon.co.uk> - July 2001 */ @@ -105,6 +105,7 @@ typedef struct { xv_property_t props[VO_NUM_PROPERTIES]; uint32_t capabilities; + xv_frame_t *recent_frames[VO_NUM_RECENT_FRAMES]; xv_frame_t *cur_frame; vo_overlay_t *overlay; @@ -292,7 +293,7 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo, shminfo->readOnly = False; image->data = shminfo->shmaddr; - + XShmAttach(this->display, shminfo); XSync(this->display, False); @@ -402,12 +403,12 @@ static void xv_update_frame_format (vo_driver_t *this_gen, frame->ratio_code = ratio_code; } -static void xv_deinterlace_frame (vo_driver_t *this_gen, - vo_frame_t *frame_gen ) { +static void xv_deinterlace_frame (xv_driver_t *this) { - xv_driver_t *this = (xv_driver_t *) this_gen; - xv_frame_t *frame = (xv_frame_t *) frame_gen; - XvImage *imgtmp; + XvImage *imgtmp; + uint8_t *recent_bitmaps[VO_NUM_RECENT_FRAMES]; + xv_frame_t *frame = this->recent_frames[0]; + int i; if ( !this->deinterlace_frame.image || (frame->width != this->deinterlace_frame.width) @@ -428,20 +429,29 @@ static void xv_deinterlace_frame (vo_driver_t *this_gen, XUnlockDisplay (this->display); } + + /* know bug: we are not deinterlacing Cb and Cr */ memcpy(this->deinterlace_frame.image->data + frame->width*frame->height, frame->image->data + frame->width*frame->height, frame->width*frame->height*1/2); +#if 0 imgtmp = this->deinterlace_frame.image; this->deinterlace_frame.image = frame->image; frame->image = imgtmp; frame->vo_frame.base[0] = frame->image->data; frame->vo_frame.base[1] = frame->image->data + frame->width * frame->height * 5 / 4; frame->vo_frame.base[2] = frame->image->data + frame->width * frame->height; +#endif + for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) + recent_bitmaps[i] = (this->recent_frames[i]) ? this->recent_frames[i]->image->data : + NULL; - deinterlace_yuv( frame->image->data, this->deinterlace_frame.image->data, + deinterlace_yuv( this->deinterlace_frame.image->data, recent_bitmaps, frame->width, frame->height, this->deinterlace_method ); + + this->cur_frame = &this->deinterlace_frame; } @@ -461,7 +471,7 @@ static void xv_adapt_to_output_area (xv_driver_t *this, this->output_yoffset = dest_y + (dest_height - this->output_height) / 2; } else { - + this->output_width = (double) dest_height * this->ratio_factor ; this->output_height = dest_height; this->output_xoffset = dest_x + (dest_width - this->output_width) / 2; @@ -490,10 +500,10 @@ static void xv_adapt_to_output_area (xv_driver_t *this, this->output_xoffset+this->output_width, dest_y, dest_width - this->output_xoffset - this->output_width, dest_height); - XUnlockDisplay (this->display); + XUnlockDisplay (this->display); } -static void xv_calc_format (xv_driver_t *this, +static void xv_calc_format (xv_driver_t *this, int width, int height, int ratio_code) { double image_ratio, desired_ratio; @@ -577,7 +587,7 @@ static void xv_calc_format (xv_driver_t *this, * ask gui to adapt to this size */ - this->request_dest_size (ideal_width, ideal_height, + this->request_dest_size (ideal_width, ideal_height, &dest_x, &dest_y, &dest_width, &dest_height); xv_adapt_to_output_area (this, dest_x, dest_y, dest_width, dest_height); @@ -599,6 +609,36 @@ static void xv_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_o } } +static void xv_add_recent_frame (xv_driver_t *this, xv_frame_t *frame) { + int i; + + i = VO_NUM_RECENT_FRAMES-1; + if( this->recent_frames[i] ) + this->recent_frames[i]->vo_frame.displayed + (&this->recent_frames[i]->vo_frame); + + for( ; i ; i-- ) + this->recent_frames[i] = this->recent_frames[i-1]; + + this->recent_frames[0] = frame; +} + +/* currently not used - we could have a method to call this from video loop */ +#if 0 +static void xv_flush_recent_frames (xv_driver_t *this) { + + int i; + + for( i=0; i < VO_NUM_RECENT_FRAMES; i++ ) + { + if( this->recent_frames[i] ) + this->recent_frames[i]->vo_frame.displayed + (&this->recent_frames[i]->vo_frame); + this->recent_frames[i] = NULL; + } +} +#endif + /* * */ @@ -609,16 +649,12 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if (this->expecting_event) { - this->expecting_event--; frame->vo_frame.displayed (&frame->vo_frame); + this->expecting_event--; } else { - - if (this->cur_frame) { - this->cur_frame->vo_frame.displayed (&this->cur_frame->vo_frame); - this->cur_frame = NULL; - } - + xv_add_recent_frame (this, frame); + this->cur_frame = frame; if ( (frame->width != this->delivered_width) || (frame->height != this->delivered_height) @@ -632,24 +668,22 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { // } if( this->deinterlace_method ) - xv_deinterlace_frame (this_gen, frame_gen ); + xv_deinterlace_frame (this); XLockDisplay (this->display); - this->cur_frame = frame; - if (this->use_shm) { XvShmPutImage(this->display, this->xv_port, - this->drawable, this->gc, frame->image, - 0, 0, frame->width, frame->height-5, + this->drawable, this->gc, this->cur_frame->image, + 0, 0, this->cur_frame->width, this->cur_frame->height-5, this->output_xoffset, this->output_yoffset, this->output_width, this->output_height, True); this->expecting_event = 10; } else { XvPutImage(this->display, this->xv_port, - this->drawable, this->gc, frame->image, - 0, 0, frame->width, frame->height-5, + this->drawable, this->gc, this->cur_frame->image, + 0, 0, this->cur_frame->width, this->cur_frame->height-5, this->output_xoffset, this->output_yoffset, this->output_width, this->output_height); } @@ -724,7 +758,7 @@ static void xv_get_property_min_max (vo_driver_t *this_gen, *max = this->props[property].max; } -static int xv_gui_data_exchange (vo_driver_t *this_gen, +static int xv_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -767,7 +801,7 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, this->output_xoffset, this->output_yoffset, this->output_width, this->output_height, False); } else { - XvPutImage(this->display, this->xv_port, + XvPutImage(this->display, this->xv_port, this->drawable, this->gc, this->cur_frame->image, 0, 0, this->cur_frame->width, this->cur_frame->height-5, this->output_xoffset, this->output_yoffset, @@ -836,7 +870,7 @@ static void xv_check_capability (xv_driver_t *this, this->props[property].max = attr.max_value; this->props[property].atom = XInternAtom (this->display, str_prop, False); this->props[property].key = str_prop; - + XvGetPortAttribute (this->display, this->xv_port, this->props[property].atom, &nDefault); @@ -995,7 +1029,7 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { printf("XV_HUE "); } else if(!strcmp(attr[k].name, "XV_SATURATION")) { - xv_check_capability (this, VO_CAP_SATURATION, + xv_check_capability (this, VO_CAP_SATURATION, VO_PROP_SATURATION, attr[k], adaptor_info[adaptor_num].base_id, "XV_SATURATION"); printf("XV_SATURATION "); @@ -1039,8 +1073,8 @@ vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen) { this->xv_format_rgb = 0; for(i = 0; i < formats; i++) { - xprintf(VERBOSE|VIDEO, "video_out_xv: Xv image format: 0x%x (%4.4s) %s\n", - fo[i].id, (char*)&fo[i].id, + xprintf(VERBOSE|VIDEO, "video_out_xv: Xv image format: 0x%x (%4.4s) %s\n", + fo[i].id, (char*)&fo[i].id, (fo[i].format == XvPacked) ? "packed" : "planar"); if (fo[i].id == IMGFMT_YV12) { this->xv_format_yv12 = fo[i].id; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index cc9d7bb62..1ec2d6147 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.h,v 1.19 2001/09/16 15:21:13 miguelfreitas Exp $ + * $Id: video_out.h,v 1.20 2001/09/19 02:40:58 miguelfreitas Exp $ * * * xine version of video_out.h @@ -176,6 +176,12 @@ struct vo_instance_s { #define VO_PROP_SOFT_DEINTERLACE 7 #define VO_NUM_PROPERTIES 8 +/* number of recent frames to keep in memory + these frames are needed by some deinterlace algorithms + FIXME: we need a method to flush the recent frames (new stream) +*/ +#define VO_NUM_RECENT_FRAMES 2 + /* image formats that can be supported by display drivers: */ #define IMGFMT_YV12 0x32315659 @@ -198,7 +204,7 @@ struct vo_instance_s { /* video driver capabilities */ -/* driver copies image (i.e. converts it to +/* driver copies image (i.e. converts it to rgb buffers in the private fields of image buffer) */ #define VO_CAP_COPIES_IMAGE 0x00000001 @@ -227,7 +233,7 @@ struct vo_driver_s { uint32_t (*get_capabilities) (vo_driver_t *this); /* for constants see above */ - /* + /* * allocate an vo_frame_t struct, * the driver must supply the copy, field and dispose functions */ @@ -317,7 +323,7 @@ vo_instance_t *vo_new_instance (vo_driver_t *driver, metronom_t *metronom) ; * visual - driver specific info (e.g. Display*) * * return value: video_driver_t* in case of success, - * NULL on failure (e.g. wrong interface version, + * NULL on failure (e.g. wrong interface version, * wrong visual type...) * * |