* modules/access/dshow/*: handle upside down pictures (a bit hacky though).
authorGildas Bazin <gbazin@videolan.org>
Wed, 27 Aug 2003 07:31:26 +0000 (07:31 +0000)
committerGildas Bazin <gbazin@videolan.org>
Wed, 27 Aug 2003 07:31:26 +0000 (07:31 +0000)
modules/access/dshow/dshow.cpp
modules/access/dshow/filter.cpp

index e562553..24b599e 100644 (file)
@@ -2,7 +2,7 @@
  * dshow.c : DirectShow access module for vlc
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: dshow.cpp,v 1.4 2003/08/26 19:14:09 gbazin Exp $
+ * $Id: dshow.cpp,v 1.5 2003/08/27 07:31:26 gbazin Exp $
  *
  * Author: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -140,6 +140,7 @@ typedef struct dshow_stream_t
     CaptureFilter   *p_capture_filter;
     AM_MEDIA_TYPE   mt;
     int             i_fourcc;
+    vlc_bool_t      b_invert;
 
     union
     {
@@ -428,6 +429,7 @@ static int OpenDevice( input_thread_t *p_input, string devicename,
     {
         /* Success */
         dshow_stream_t dshow_stream;
+        dshow_stream.b_invert = VLC_FALSE;
         dshow_stream.mt =
             p_capture_filter->CustomGetPin()->CustomGetMediaType();
 
@@ -467,6 +469,19 @@ static int OpenDevice( input_thread_t *p_input, string devicename,
             dshow_stream.header.video =
                 *(VIDEOINFOHEADER *)dshow_stream.mt.pbFormat;
 
+            int i_height = dshow_stream.header.video.bmiHeader.biHeight;
+
+            /* Check if the image is inverted (bottom to top) */
+            if( dshow_stream.i_fourcc == VLC_FOURCC( 'R', 'V', '1', '5' ) ||
+                dshow_stream.i_fourcc == VLC_FOURCC( 'R', 'V', '1', '6' ) ||
+                dshow_stream.i_fourcc == VLC_FOURCC( 'R', 'V', '2', '4' ) ||
+                dshow_stream.i_fourcc == VLC_FOURCC( 'R', 'V', '3', '2' ) ||
+                dshow_stream.i_fourcc == VLC_FOURCC( 'R', 'G', 'B', 'A' ) )
+            {
+                if( i_height > 0 ) dshow_stream.b_invert = VLC_TRUE;
+                else i_height = - i_height;
+            }
+
             /* Add video stream to header */
             p_sys->i_header_size += 20;
             p_sys->p_header = (uint8_t *)realloc( p_sys->p_header,
@@ -476,8 +491,7 @@ static int OpenDevice( input_thread_t *p_input, string devicename,
                      &dshow_stream.i_fourcc, 4 );
             SetDWBE( &p_sys->p_header[p_sys->i_header_pos + 8],
                      dshow_stream.header.video.bmiHeader.biWidth );
-            SetDWBE( &p_sys->p_header[p_sys->i_header_pos + 12],
-                     dshow_stream.header.video.bmiHeader.biHeight );
+            SetDWBE( &p_sys->p_header[p_sys->i_header_pos + 12], i_height );
             SetDWBE( &p_sys->p_header[p_sys->i_header_pos + 16], 0 );
             p_sys->i_header_pos = p_sys->i_header_size;
         }
@@ -683,10 +697,79 @@ static int Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
             int i_copy = __MIN( p_stream->i_data_size -
                                 p_stream->i_data_pos, (int)i_len );
 
-            memcpy( p_buffer, &p_stream->p_data[p_stream->i_data_pos],
-                    i_copy );
-            p_stream->i_data_pos += i_copy;
+            if( !p_stream->b_invert )
+            {
+                p_input->p_vlc->pf_memcpy( p_buffer,
+                    &p_stream->p_data[p_stream->i_data_pos], i_copy );
+            }
+            else
+            {
+                int i_copied;
+                int i_width = p_stream->header.video.bmiHeader.biWidth;
+                int i_height = p_stream->header.video.bmiHeader.biHeight;
+
+                switch( p_stream->i_fourcc )
+                {
+                case VLC_FOURCC( 'R', 'V', '1', '5' ):
+                case VLC_FOURCC( 'R', 'V', '1', '6' ):
+                    i_width *= 2;
+                    break;
+                case VLC_FOURCC( 'R', 'V', '2', '4' ):
+                    i_width *= 3;
+                    break;
+                case VLC_FOURCC( 'R', 'V', '3', '2' ):
+                case VLC_FOURCC( 'R', 'G', 'B', 'A' ):
+                    i_width *= 4;
+                    break;
+                }
+
+                int i_line_pos = i_height - 1 - p_stream->i_data_pos / i_width;
+                int i_offset = p_stream->i_data_pos % i_width;
+
+                i_copied = __MIN( i_width - i_offset, i_copy );
 
+                /* copy already started line if any */
+                if( i_copied )
+                {
+                    memcpy( p_buffer,
+                            &p_stream->p_data[i_line_pos * i_width + i_offset],
+                            i_copied );
+
+                    p_stream->i_data_pos += i_copied;
+                    p_buffer += i_copied;
+                    i_len -= i_copied;
+                    i_data += i_copied;
+                    i_copy -= i_copied;
+                }
+
+                /* The caller got what he wanted */
+                if( i_len <= 0 ) return i_data;
+
+                i_line_pos = i_height - 1 - p_stream->i_data_pos / i_width;
+                i_copied = i_copy / i_width;
+
+                while( i_copied )
+                {
+                    memcpy( p_buffer, &p_stream->p_data[i_line_pos * i_width],
+                            i_width );
+                    p_stream->i_data_pos += i_width;
+                    p_buffer += i_width;
+                    i_len -= i_width;
+                    i_data += i_width;
+                    i_copy -= i_width;
+                    i_line_pos--;
+                    i_copied--;
+                }
+
+                /* copy left over if any */
+                if( i_copy )
+                {
+                    memcpy( p_buffer, &p_stream->p_data[i_line_pos * i_width],
+                            i_copy );
+                }
+            }
+
+            p_stream->i_data_pos += i_copy;
             p_buffer += i_copy;
             i_len -= i_copy;
             i_data += i_copy;
@@ -704,7 +787,11 @@ static int Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
         }
 
         /* Get new sample/frame from next stream */
-        //if( p_stream->sample.p_sample ) p_stream->sample.p_sample->Release();
+        if( p_stream->sample.p_sample )
+        {
+            p_stream->sample.p_sample->Release();
+            p_stream->sample.p_sample = NULL;
+        }
         p_sys->i_current_stream =
             (p_sys->i_current_stream + 1) % p_sys->i_streams;
         p_stream = p_sys->pp_streams[p_sys->i_current_stream];
@@ -729,7 +816,8 @@ static int Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
             }
 
 #if 0
-            msg_Dbg( p_input, "Read() PTS: "I64Fd, i_pts );
+            msg_Dbg( p_input, "Read() stream: %i PTS: "I64Fd,
+                     p_sys->i_current_stream, i_pts );
 #endif
 
             /* Create pseudo header */
@@ -739,7 +827,7 @@ static int Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
             SetDWBE( &p_sys->p_header[4], p_stream->i_data_size );
             SetQWBE( &p_sys->p_header[8], i_pts  * 9 / 1000 );
         }
-        else msleep( 10000 );
+        else msleep( 1000 );
     }
 
     return i_data;
index de57919..6c4d0dd 100644 (file)
@@ -2,7 +2,7 @@
  * filter.c : DirectShow access module for vlc
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: filter.cpp,v 1.3 2003/08/26 19:14:10 gbazin Exp $
+ * $Id: filter.cpp,v 1.4 2003/08/27 07:31:26 gbazin Exp $
  *
  * Author: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -387,7 +387,7 @@ STDMETHODIMP CapturePin::Receive( IMediaSample *pSample )
     //msg_Dbg( p_input, "CapturePin::Receive" );
 #endif
 
-    //pSample->AddRef();
+    pSample->AddRef();
     mtime_t i_timestamp = mdate() * 10;
     VLCMediaSample vlc_sample = {pSample, i_timestamp};
     samples_queue.push_front( vlc_sample );
@@ -398,7 +398,7 @@ STDMETHODIMP CapturePin::Receive( IMediaSample *pSample )
         vlc_sample = samples_queue.back();
         samples_queue.pop_back();
         msg_Dbg( p_input, "CapturePin::Receive trashing late input sample" );
-        // vlc_sample.p_sample->Release();
+        vlc_sample.p_sample->Release();
     }
 
     return S_OK;