cinepak: fix a bug (bad frame gathering), pointed by sam.
authorLaurent Aimar <fenrir@videolan.org>
Wed, 27 Nov 2002 13:17:27 +0000 (13:17 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Wed, 27 Nov 2002 13:17:27 +0000 (13:17 +0000)
modules/codec/cinepak/cinepak.c
modules/codec/cinepak/cinepak.h

index 8b900d9..1a1e125 100644 (file)
@@ -2,7 +2,7 @@
  * cinepak.c: cinepak video decoder 
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: cinepak.c,v 1.6 2002/10/27 16:58:14 gbazin Exp $
+ * $Id: cinepak.c,v 1.7 2002/11/27 13:17:27 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -156,60 +156,37 @@ static inline u32 GetDWBE( u8 *p_buff )
     if( p ) free( p )
 
 
-static inline void __GetFrame( videodec_thread_t *p_vdec )
-{
-    pes_packet_t  *p_pes;
-    data_packet_t *p_data;
-    byte_t        *p_buffer;
+static void GetPESData( u8 *p_buf, int i_max, pes_packet_t *p_pes )
+{   
+    int i_copy; 
+    int i_count;
+
+    data_packet_t   *p_data;
 
-    input_ExtractPES( p_vdec->p_fifo, &p_pes );
-    if( !p_pes )
+    i_count = 0;
+    p_data = p_pes->p_first;
+    while( p_data != NULL && i_count < i_max )
     {
-        p_vdec->p_framedata = NULL;
-        return;
-    }
 
-    p_vdec->i_pts = p_pes->i_pts;
+        i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start, 
+                        i_max - i_count );
 
-    while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
-    {
-        input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
-        input_ExtractPES( p_vdec->p_fifo, &p_pes );
-        if( !p_pes )
+        if( i_copy > 0 )
         {
-            p_vdec->p_framedata = NULL;
-            return;
+            memcpy( p_buf,
+                    p_data->p_payload_start,
+                    i_copy );
         }
-    }
-    p_vdec->i_framesize = p_pes->i_pes_size;
-    if( p_pes->i_nb_data == 1 )
-    {
-        p_vdec->p_framedata = p_pes->p_first->p_payload_start;
-        return;    
-    }
-    /* get a buffer and gather all data packet */
-    p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
-    p_data = p_pes->p_first;
-    do
-    {
-        p_vdec->p_fifo->p_vlc->pf_memcpy( p_buffer, p_data->p_payload_start, 
-                     p_data->p_payload_end - p_data->p_payload_start );
-        p_buffer += p_data->p_payload_end - p_data->p_payload_start;
-        p_data = p_data->p_next;
-    } while( p_data );
-    input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
-}
 
-static inline void __NextFrame( videodec_thread_t *p_vdec )
-{
-    pes_packet_t  *p_pes;
+        p_data = p_data->p_next;
+        i_count += i_copy;
+        p_buf   += i_copy;
+    }
 
-    input_ExtractPES( p_vdec->p_fifo, &p_pes );
-    if( p_pes && (p_pes->i_nb_data != 1) )
+    if( i_count < i_max )
     {
-        free( p_vdec->p_framedata ); /* FIXME keep this buffer */
+        memset( p_buf, 0, i_max - i_count );
     }
-    input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
 }
 
 static int cinepak_CheckVout( vout_thread_t *p_vout,
@@ -819,23 +796,48 @@ static int InitThread( videodec_thread_t *p_vdec )
  *****************************************************************************/
 static void  DecodeThread( videodec_thread_t *p_vdec )
 {
+    pes_packet_t    *p_pes;
+    int             i_frame_size;
+                
     int     i_status;
-    
     int i_plane;
     u8 *p_dst, *p_src;
     picture_t *p_pic; /* videolan picture */
 
-    __GetFrame( p_vdec );
+    do
+    {
+        input_ExtractPES( p_vdec->p_fifo, &p_pes );
+        if( !p_pes )
+        {
+            p_vdec->p_fifo->b_error = 1;
+            return;
+        }
+        p_vdec->i_pts = p_pes->i_pts;
+        i_frame_size = p_pes->i_pes_size;
+
+        if( i_frame_size > 0 )
+        {
+            if( p_vdec->i_buffer < i_frame_size + 16 )
+            {
+                FREE( p_vdec->p_buffer );
+                p_vdec->p_buffer = malloc( i_frame_size + 16 );
+                p_vdec->i_buffer = i_frame_size + 16;
+            }
 
+            GetPESData( p_vdec->p_buffer, p_vdec->i_buffer, p_pes );
+        }
+        input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
+    } while( i_frame_size <= 0 );
+
+    
     i_status = cinepak_decode_frame( p_vdec->p_context,
-                                     p_vdec->i_framesize,
-                                     p_vdec->p_framedata );
-    __NextFrame( p_vdec );
+                                     i_frame_size,
+                                     p_vdec->p_buffer );
                                          
     if( i_status < 0 )
     {
         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
-                                  p_vdec->i_framesize );
+                                  i_frame_size );
         return;
     }
     
index df73d3c..1dbfa96 100644 (file)
@@ -2,7 +2,7 @@
  * cinepak.h: Cinepak video decoder
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: cinepak.h,v 1.1 2002/08/04 17:23:42 sam Exp $
+ * $Id: cinepak.h,v 1.2 2002/11/27 13:17:27 fenrir Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
@@ -62,6 +62,9 @@ typedef struct videodec_thread_s
 
     /* private */
     mtime_t i_pts;
-    int     i_framesize;
-    byte_t  *p_framedata;
+    u8      *p_buffer;      /* buffer for gather pes */  \
+    int     i_buffer;       /* size of allocated p_framedata */
+    
+//    int     i_framesize;
+//    byte_t  *p_framedata;
 } videodec_thread_t;