/** * Copyright (C) 2001 Billy Biggs . * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include "videoinput.h" #include "dfboutput.h" /** * Set this to 0 to see b/w output. */ #define SHOW_COLOUR 1 /** * Set this to your V4L device. */ #define V4L_DEVICE "/dev/video0" /** * Set this to your V4L input number (mine is 0 for tuner). */ #define V4L_INPUT 0 /** * Set this to be in PAL mode. */ #define PAL_MODE 0 /** * These next functions will be better optimized soon. */ static inline void clear_scanline_packed_422( unsigned char *output, int size ) { static int clear = 128 << 24 | 16 << 16 | 128 << 8 | 16; unsigned int *o = (unsigned int *) output; for( size /= 4; size; --size ) { *o++ = clear; } } static inline void copy_scanline_packed_422( unsigned char *output, unsigned char *luma, unsigned char *cb, unsigned char *cr, int width ) { unsigned int *o = (unsigned int *) output; if( SHOW_COLOUR ) { for( width /= 2; width; --width ) { *o = (*cr << 24) | (*(luma + 1) << 16) | (*cb << 8) | (*luma); o++; luma += 2; cb++; cr++; } } else { for( width /= 2; width; --width ) { *o = (128 << 24) | (*(luma + 1) << 16) | (128 << 8) | (*luma); o++; luma += 2; } } } static void build_packed_422_field( unsigned char *output, unsigned char *fieldluma, unsigned char *fieldcb, unsigned char *fieldcr, int bottom_field, int lstride, int cstride, int width, int height, int ostride ) { int i; if( bottom_field ) { /* Skip a scanline. */ output += ostride; /* Copy a scanline. */ copy_scanline_packed_422( output, fieldluma, fieldcb, fieldcr, width ); output += ostride; } for( i = 0; i < (height / 2) - 1; i++ ) { if( !bottom_field ) { /* Copy a scanline. */ copy_scanline_packed_422( output, fieldluma, fieldcb, fieldcr, width ); output += ostride; } /* Skip a scanline. */ output += ostride; fieldluma += lstride; fieldcb += cstride; fieldcr += cstride; if( bottom_field ) { /* Copy a scanline. */ copy_scanline_packed_422( output, fieldluma, fieldcb, fieldcr, width ); output += ostride; } } if( !bottom_field ) { /* Copy a scanline. */ copy_scanline_packed_422( output, fieldluma, fieldcb, fieldcr, width ); output += ostride; } } int main( int argc, char **argv ) { videoinput_t *vidin; int width, height, pitch; int inputnum = V4L_INPUT; char *fb_dev_name = 0; vidin = videoinput_new( V4L_DEVICE, inputnum, 720, PAL_MODE ? 576 : 480, PAL_MODE ); if( !vidin ) { fprintf( stderr, "tvtime: Can't open video input, " "maybe try a different device?\n" ); return 1; } /* Get the input width and height. */ width = videoinput_get_width( vidin ); height = videoinput_get_height( vidin ); /* Init dfb. */ if( !(fb_dev_name = getenv( "FRAMEBUFFER" )) ) { fb_dev_name = "/dev/fb0"; } if( !dfb_init( fb_dev_name, PAL_MODE ) ) { return 1; } /* Setup the video input. */ videoinput_free_all_frames( vidin ); /* Listen for ESC and do our work. */ while( !dfb_pollevents() ) { unsigned char *curluma = videoinput_next_image( vidin ); unsigned char *curcb422 = curluma + ( width * height ); unsigned char *curcr422 = curcb422 + ( width/2 * height ); /* Make sure we're scheduled to output a top field. */ while( dfb_getcurrentoutputfield() != 0 ) { if( dfb_pollevents() ) { dfb_uninit(); return 1; } fprintf( stderr, "Resyncing...\n" ); dfb_waitforsync(); } /* Build the top field */ dfb_lockframebuffer(); pitch = dfb_get_pitch(); build_packed_422_field( dfb_getframebuffer(), curluma, curcb422, curcr422, 0, width * 2, width, width, height, pitch ); dfb_unlockframebuffer(); /* We're done with the input now. */ videoinput_free_last_frame( vidin ); /* Wait for sync */ dfb_waitforsync(); /* Build the bottom field */ dfb_lockframebuffer(); pitch = dfb_get_pitch(); build_packed_422_field( dfb_getframebuffer(), curluma + width, curcb422 + (width / 2), curcr422 + (width / 2), 1, width * 2, width, width, height, pitch ); dfb_unlockframebuffer(); /* Wait for sync */ dfb_waitforsync(); } dfb_uninit(); return 0; }