[vlc-commits] [Git][videolan/vlc][master] 18 commits: demux: avi: account header outside of sample size

Steve Lhomme (@robUx4) gitlab at videolan.org
Tue Nov 1 10:23:15 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
c8fe3d81 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: account header outside of sample size

- - - - -
c6cc1df8 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: move around code to ease understanding

- - - - -
b354b052 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: remove unneeded temp var/refetch

- - - - -
9836217e by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: add comments

- - - - -
4502f33c by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: set frame flags on video_es only

- - - - -
58aba619 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: simplify audio seek computation

- - - - -
4ea55641 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: replace useless define

- - - - -
cfc23381 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: replace redundant track lookups

- - - - -
2bb10868 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: add proper check for index alloc

- - - - -
4ed9fa53 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: interleave 0 samplesize PCM

Avoids sending [a single] montrosample[s]

refs #27393

- - - - -
817e0d30 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: return insert position on indexAppend

- - - - -
b108e622 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: fix bogus indexless sample reads

was always using the previous chunk size

refs #27425

- - - - -
bb629537 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: change index non fatal messages to warning

- - - - -
13e48e51 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: add QNap fourcc defines

- - - - -
6853c770 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: fix peek beyond QNap header

- - - - -
34710736 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: extract meta from QNap header

- - - - -
9bb482ba by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: avi: fix unmatched video codec

Parsing bitmapinfoheader resets to MS fourcc.
Demuxer's codec conditionals cannot match.

- - - - -
0acdec00 by Francois Cartegnie at 2022-11-01T10:10:28+00:00
demux: libavi: use only typedef'ed anon structs

- - - - -


4 changed files:

- modules/demux/avi/avi.c
- modules/demux/avi/bitmapinfoheader.h
- modules/demux/avi/libavi.c
- modules/demux/avi/libavi.h


Changes:

=====================================
modules/demux/avi/avi.c
=====================================
@@ -35,6 +35,7 @@
 #include <vlc_plugin.h>
 #include <vlc_demux.h>
 #include <vlc_input.h>
+#include <vlc_aout.h>
 
 #include <vlc_dialog.h>
 
@@ -135,7 +136,7 @@ typedef struct
 } avi_index_t;
 static void avi_index_Init( avi_index_t * );
 static void avi_index_Clean( avi_index_t * );
-static void avi_index_Append( avi_index_t *, uint64_t *, avi_entry_t * );
+static int64_t avi_index_Append( avi_index_t *, uint64_t *, avi_entry_t * );
 
 typedef struct
 {
@@ -147,6 +148,7 @@ typedef struct
     unsigned int    i_samplesize;
 
     struct bitmapinfoheader_properties bihprops;
+    bool            is_qnap;
 
     es_format_t     fmt;
     es_out_id_t     *p_es;
@@ -191,6 +193,7 @@ typedef struct
 
     /* meta */
     vlc_meta_t  *meta;
+    unsigned int updates;
 
     unsigned int       i_attachment;
     input_attachment_t **attachment;
@@ -204,14 +207,12 @@ static vlc_tick_t AVI_GetDPTS   ( avi_track_t *, int64_t i_count );
 static vlc_tick_t AVI_GetPTS    ( avi_track_t * );
 
 
-static int AVI_StreamChunkFind( demux_t *, unsigned int i_stream );
-static int AVI_StreamChunkSet ( demux_t *,
-                                unsigned int i_stream, unsigned int i_ck );
-static int AVI_StreamBytesSet ( demux_t *,
-                                unsigned int i_stream, uint64_t i_byte );
+static int AVI_StreamChunkFind( demux_t *, avi_track_t * );
+static int AVI_StreamChunkSet ( demux_t *, avi_track_t *, unsigned int i_ck );
+static int AVI_StreamBytesSet ( demux_t *, avi_track_t *, uint64_t i_byte );
 
 vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
-static int   AVI_GetKeyFlag    ( vlc_fourcc_t , uint8_t * );
+static int   AVI_GetKeyFlag    ( const avi_track_t *, const uint8_t * );
 
 static int AVI_PacketGetHeader( demux_t *, avi_packet_t *p_pk );
 static int AVI_PacketNext     ( demux_t * );
@@ -243,20 +244,21 @@ static int        AVI_TrackStopFinishedStreams( demux_t *);
  - to complete....
  */
 
-#define QNAP_HEADER_SIZE 56
-static bool IsQNAPCodec(vlc_fourcc_t codec)
+#define QNAP_VIDEO_HEADER_SIZE 56
+/* https://github.com/qnap-dev/qnap-qiot-sdks/blob/master/doc/QVRPro/live_stream_parser.cpp#L90 */
+static bool IsQNAPCodec(uint32_t biCompression)
 {
-    switch (codec)
-    {
-        case VLC_FOURCC('w', '2', '6', '4'):
-        case VLC_FOURCC('q', '2', '6', '4'):
-        case VLC_FOURCC('Q', '2', '6', '4'):
-        case VLC_FOURCC('w', 'M', 'P', '4'):
-        case VLC_FOURCC('q', 'M', 'P', '4'):
-        case VLC_FOURCC('Q', 'M', 'P', '4'):
-        case VLC_FOURCC('w', 'I', 'V', 'G'):
-        case VLC_FOURCC('q', 'I', 'V', 'G'):
-        case VLC_FOURCC('Q', 'I', 'V', 'G'):
+    switch (biCompression)
+    {
+        case QNAP_FCC_w264:
+        case QNAP_FCC_q264:
+        case QNAP_FCC_Q264:
+        case QNAP_FCC_wMP4:
+        case QNAP_FCC_qMP4:
+        case QNAP_FCC_QMP4:
+        case QNAP_FCC_wIVG:
+        case QNAP_FCC_qIVG:
+        case QNAP_FCC_QIVG:
             return true;
         default:
             return false;
@@ -503,14 +505,27 @@ static int Open( vlc_object_t * p_this )
                     tk->fmt.i_codec = AVI_FourccGetCodec( AUDIO_ES, p_auds->p_wf->wFormatTag );
 
                 tk->i_blocksize = p_auds->p_wf->nBlockAlign;
-                if( tk->i_blocksize == 0 )
+
+                /* Fix blocksize == 0 and force interleaving PCM chunks samplesize == 0 */
+                if( tk->i_samplesize == 0 || tk->i_blocksize == 0 )
                 {
-                    if( p_auds->p_wf->wFormatTag == 1 )
-                        tk->i_blocksize = p_auds->p_wf->nChannels * (p_auds->p_wf->wBitsPerSample/8);
-                    else
+                    vlc_fourcc_t i_codec = vlc_fourcc_GetCodecAudio( tk->fmt.i_codec,
+                                                                     p_auds->p_wf->wBitsPerSample );
+                    unsigned bps = aout_BitsPerSample( i_codec );
+                    if( bps > 0 ) /* PCM audio */
+                    {
+                        if( tk->i_blocksize == 0 )
+                            tk->i_blocksize = bps * p_auds->p_wf->nChannels / 8;
+                        if( tk->i_samplesize == 0 )
+                            tk->i_samplesize = tk->i_blocksize;
+                        tk->fmt.b_packetized = true;
+                    }
+                    else if( tk->i_blocksize == 0 )
+                    {
                         tk->i_blocksize = 1;
+                    }
                 }
-                else if( tk->i_samplesize != 0 && tk->i_samplesize != tk->i_blocksize )
+                else if( tk->i_samplesize != tk->i_blocksize )
                 {
                     msg_Warn( p_demux, "track[%u] samplesize=%u and blocksize=%u are not equal."
                                        "Using blocksize as a workaround.",
@@ -599,8 +614,7 @@ static int Open( vlc_object_t * p_this )
                    break;
                 }
 
-                es_format_Init( &tk->fmt, VIDEO_ES,
-                        AVI_FourccGetCodec( VIDEO_ES, p_vids->p_bih->biCompression ) );
+                es_format_Init( &tk->fmt, VIDEO_ES, 0 );
 
                 if( ParseBitmapInfoHeader( p_vids->p_bih, p_vids->i_chunk_size, &tk->fmt,
                                            &tk->bihprops ) != VLC_SUCCESS )
@@ -617,8 +631,11 @@ static int Open( vlc_object_t * p_this )
                     tk->fmt.i_original_fourcc = VLC_FOURCC( 'X', 'V', 'I', 'D' );
                 }
 
-                if( IsQNAPCodec( tk->fmt.i_codec ) )
+                if( IsQNAPCodec( p_vids->p_bih->biCompression ) )
+                {
+                    tk->is_qnap = true;
                     tk->fmt.b_packetized = false;
+                }
 
                 tk->i_samplesize = 0;
                 tk->fmt.video.i_frame_rate = tk->i_rate;
@@ -832,26 +849,33 @@ error:
  *****************************************************************************/
 
 static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
-                     const unsigned int i_header, const int i_size )
+                            uint32_t i_header, uint32_t i_size )
 {
-    block_t *p_frame = vlc_stream_Block( p_demux->s, __EVEN( i_size ) );
-    if ( !p_frame ) return p_frame;
-
-    if( i_size % 2 )    /* read was padded on word boundary */
+    /* skip header */
+    if( i_header )
     {
-        p_frame->i_buffer--;
+        assert(i_header % 8 == 0);
+        ssize_t i_skip = vlc_stream_Read( p_demux->s, NULL, i_header );
+        if( i_skip < 0 || (size_t) i_skip < i_header )
+            return NULL;
     }
 
-    if( i_header >= p_frame->i_buffer || tk->bihprops.i_stride > INT32_MAX - 3 )
+    /* read size padded on word boundary */
+    i_size = __EVEN(i_size);
+
+    if( i_size == 0 )
+        return block_Alloc(0); /* vlc_stream_Block can't read/alloc 0 sized */
+
+    block_t *p_frame = vlc_stream_Block( p_demux->s, i_size );
+    if ( !p_frame )
+        return p_frame;
+
+    if( tk->bihprops.i_stride > INT32_MAX - 3 )
     {
         p_frame->i_buffer = 0;
         return p_frame;
     }
 
-    /* skip header */
-    p_frame->p_buffer += i_header;
-    p_frame->i_buffer -= i_header;
-
     const unsigned int i_stride_bytes = (tk->bihprops.i_stride + 3) & ~3;
 
     if ( !tk->bihprops.i_stride || !i_stride_bytes )
@@ -914,6 +938,8 @@ static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
  *****************************************************************************/
 static void AVI_SendFrame( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
 {
+    demux_sys_t *p_sys = p_demux->p_sys;
+
     if( tk->fmt.i_cat != VIDEO_ES )
         p_frame->i_dts = p_frame->i_pts;
     else
@@ -925,17 +951,32 @@ static void AVI_SendFrame( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
     if( tk->i_dv_audio_rate )
         AVI_DvHandleAudio( p_demux, tk, p_frame );
 
-    /* Strip QNAP header */
-    if( IsQNAPCodec( tk->fmt.i_codec ) )
+    /* Strip 3rd party header */
+    if( tk->is_qnap )
     {
-        if( p_frame->i_buffer <= QNAP_HEADER_SIZE )
+        if( p_frame->i_buffer >= QNAP_VIDEO_HEADER_SIZE )
         {
-            block_Release( p_frame );
-            return;
+            const uint8_t *p = p_frame->p_buffer;
+            /* Check header is really there */
+            vlc_fourcc_t fcc = VLC_FOURCC(p[0],p[1],p[2],p[3]);
+            /* Parse QNAP header */
+            if( IsQNAPCodec(fcc) && p_sys->meta )
+            {
+                const char *psz_title = vlc_meta_Get( p_sys->meta, vlc_meta_Title );
+                char *psz_osd = (char *) &p_frame->p_buffer[24];
+                if( *psz_osd != 0 )
+                {
+                    psz_osd[23] = 0;
+                    if( !psz_title || strncmp( psz_osd, psz_title, 24 ) )
+                    {
+                        vlc_meta_Set( p_sys->meta, vlc_meta_Title, psz_osd );
+                        p_sys->updates |= INPUT_UPDATE_META;
+                    }
+                }
+            }
+            p_frame->i_buffer -= QNAP_VIDEO_HEADER_SIZE;
+            p_frame->p_buffer += QNAP_VIDEO_HEADER_SIZE;
         }
-
-        p_frame->i_buffer -= QNAP_HEADER_SIZE;
-        p_frame->p_buffer += QNAP_HEADER_SIZE;
     }
 
     if( tk->i_next_block_flags )
@@ -1073,7 +1114,6 @@ static int Demux_Seekable( demux_t *p_demux )
         block_t         *p_frame;
         int64_t i_pos;
         unsigned int i;
-        size_t i_size;
 
         /* search for first chunk to be read */
         for( i = 0, b_done = true, i_pos = -1; i < p_sys->i_track; i++ )
@@ -1165,15 +1205,18 @@ static int Demux_Seekable( demux_t *p_demux )
                     /* add this chunk to the index */
                     avi_entry_t index;
                     index.i_id     = avi_pk.i_fourcc;
-                    index.i_flags  = AVI_GetKeyFlag(tk->fmt.i_codec, avi_pk.i_peek);
+                    index.i_flags  = AVI_GetKeyFlag(tk, avi_pk.i_peek);
                     index.i_pos    = avi_pk.i_pos;
                     index.i_length = avi_pk.i_size;
                     index.i_lengthtotal = index.i_length;
-                    avi_index_Append( &tk->idx, &p_sys->i_movi_lastchunk_pos, &index );
+                    int64_t i_indexid = avi_index_Append( &tk->idx, &p_sys->i_movi_lastchunk_pos, &index );
 
                     /* do we will read this data ? */
-                    if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -p_sys->i_read_increment )
+                    if( i_indexid >= 0 &&
+                        AVI_GetDPTS( tk, toread[i_track].i_toread ) > -p_sys->i_read_increment )
                     {
+                        tk->i_idxposc = (unsigned int) i_indexid;
+                        tk->i_idxposb = 0;
                         break;
                     }
                     else
@@ -1198,11 +1241,16 @@ static int Demux_Seekable( demux_t *p_demux )
         /* Set the track to use */
         tk = p_sys->track[i_track];
 
+        size_t i_size;
+        unsigned i_ck_remaining_bytes = tk->idx.p_entry[tk->i_idxposc].i_length -
+                                        tk->i_idxposb;
+
         /* read those data */
         if( tk->i_samplesize )
         {
             int64_t i_toread;
 
+            /* remaining bytes to read inside the current read increment */
             if( ( i_toread = toread[i_track].i_toread ) <= 0 )
             {
                 if( tk->i_samplesize > 1 )
@@ -1211,26 +1259,23 @@ static int Demux_Seekable( demux_t *p_demux )
                 }
                 else
                 {
+                    /* refill current read increment */
                     i_toread = AVI_PTSToByte( tk, VLC_TICK_FROM_MS(20) );
                     i_toread = __MAX( i_toread, 100 );
                 }
             }
-            i_size = __MIN( tk->idx.p_entry[tk->i_idxposc].i_length -
-                                tk->i_idxposb,
-                            (size_t) i_toread );
+            i_size = __MIN( i_ck_remaining_bytes, (size_t) i_toread );
         }
         else
         {
-            i_size = tk->idx.p_entry[tk->i_idxposc].i_length;
+            assert(tk->i_idxposb == 0);
+            i_size = i_ck_remaining_bytes;
         }
 
-        if( tk->i_idxposb == 0 )
-        {
-            i_size += 8; /* need to read and skip header */
-        }
+        /* need to read and skip tag/header */
+        const uint8_t i_header = ( tk->i_idxposb == 0 ) ? 8 : 0;
 
-        if( ( p_frame = ReadFrame( p_demux, tk,
-                        ( tk->i_idxposb == 0 ) ? 8 : 0, i_size ) )==NULL )
+        if( ( p_frame = ReadFrame( p_demux, tk, i_header, i_size ) )==NULL )
         {
             msg_Warn( p_demux, "failed reading data" );
             tk->b_eof = false;
@@ -1243,18 +1288,14 @@ static int Demux_Seekable( demux_t *p_demux )
         {
             p_frame->i_flags = BLOCK_FLAG_TYPE_I;
         }
-        else
+        else if( tk->fmt.i_cat == VIDEO_ES )
         {
             p_frame->i_flags = BLOCK_FLAG_TYPE_PB;
         }
 
-        /* read data */
+        /* advance chunk/byte pointers */
         if( tk->i_samplesize )
         {
-            if( tk->i_idxposb == 0 )
-            {
-                i_size -= 8;
-            }
             toread[i_track].i_toread -= i_size;
             tk->i_idxposb += i_size;
             if( tk->i_idxposb >=
@@ -1264,18 +1305,18 @@ static int Demux_Seekable( demux_t *p_demux )
                 tk->i_idxposc++;
             }
         }
-        else
+        else /* full chunk */
         {
-            int i_length = tk->idx.p_entry[tk->i_idxposc].i_length;
-
+            /* Goto to next chunk */
             tk->i_idxposc++;
             if( tk->fmt.i_cat == AUDIO_ES )
             {
-                tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
+                tk->i_blockno += tk->i_blocksize > 0 ? ( i_size + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
             }
             toread[i_track].i_toread--;
         }
 
+        /* check new chunk and set new read pos */
         if( tk->i_idxposc < tk->idx.i_size)
         {
             toread[i_track].i_posf =
@@ -1286,7 +1327,7 @@ static int Demux_Seekable( demux_t *p_demux )
             }
 
         }
-        else
+        else /* all chunks read for this track */
         {
             toread[i_track].i_posf = -1;
         }
@@ -1402,7 +1443,7 @@ static int Demux_UnSeekable( demux_t *p_demux )
                         AVI_GetPTS( p_stream_master ) )< VLC_TICK_FROM_SEC(2) )
             {
                 /* load it and send to decoder */
-                block_t *p_frame = ReadFrame( p_demux, p_stream, 8, avi_pk.i_size + 8 ) ;
+                block_t *p_frame = ReadFrame( p_demux, p_stream, 8, avi_pk.i_size ) ;
                 if( p_frame == NULL )
                 {
                     return VLC_DEMUXER_EGENERIC;
@@ -1478,13 +1519,12 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_acc
         if( p_sys->i_length == 0 )
         {
             avi_track_t *p_stream = NULL;
-            unsigned i_stream = 0;
             uint64_t i_pos;
 
             if ( !p_sys->i_movi_lastchunk_pos && /* set when index is successfully loaded */
                  ! ( p_sys->i_avih_flags & AVIF_ISINTERLEAVED ) )
             {
-                msg_Err( p_demux, "seeking without index at %2.2f%%"
+                msg_Warn( p_demux, "seeking without index at %2.2f%%"
                          " only works for interleaved files", f_ratio * 100 );
                 goto failandresetpos;
             }
@@ -1507,7 +1547,6 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_acc
                     continue;
 
                 p_stream = p_track;
-                i_stream = i;
                 if( !p_track->b_eof )
                     break;
             }
@@ -1518,7 +1557,7 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_acc
             }
 
             /* be sure that the index exist */
-            if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) )
+            if( AVI_StreamChunkSet( p_demux, p_stream, 0 ) )
             {
                 msg_Warn( p_demux, "cannot seek" );
                 goto failandresetpos;
@@ -1529,7 +1568,7 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_acc
             {
                 /* search after i_idxposc */
                 if( AVI_StreamChunkSet( p_demux,
-                                        i_stream, p_stream->i_idxposc + 1 ) )
+                                        p_stream, p_stream->i_idxposc + 1 ) )
                 {
                     msg_Warn( p_demux, "cannot seek" );
                     goto failandresetpos;
@@ -1710,6 +1749,14 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             return VLC_EGENERIC;
         }
 
+        case DEMUX_TEST_AND_CLEAR_FLAGS:
+        {
+            unsigned *restrict flags = va_arg( args, unsigned * );
+            *flags &= p_sys->updates;
+            p_sys->updates &= ~*flags;
+            return VLC_SUCCESS;
+        }
+
         case DEMUX_CAN_PAUSE:
         case DEMUX_SET_PAUSE_STATE:
         case DEMUX_CAN_CONTROL_PACE:
@@ -1807,7 +1854,7 @@ static vlc_tick_t AVI_GetPTS( avi_track_t *tk )
         return AVI_GetDPTS( tk, tk->i_idxposc );
 }
 
-static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream )
+static int AVI_StreamChunkFind( demux_t *p_demux, avi_track_t *tk )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
     avi_packet_t avi_pk;
@@ -1855,13 +1902,13 @@ static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream )
             /* add this chunk to the index */
             avi_entry_t index;
             index.i_id     = avi_pk.i_fourcc;
-            index.i_flags  = AVI_GetKeyFlag(tk_pk->fmt.i_codec, avi_pk.i_peek);
+            index.i_flags  = AVI_GetKeyFlag(tk_pk, avi_pk.i_peek);
             index.i_pos    = avi_pk.i_pos;
             index.i_length = avi_pk.i_size;
             index.i_lengthtotal = index.i_length;
             avi_index_Append( &tk_pk->idx, &p_sys->i_movi_lastchunk_pos, &index );
 
-            if( avi_pk.i_stream == i_stream  )
+            if( tk_pk == tk )
             {
                 return VLC_SUCCESS;
             }
@@ -1875,12 +1922,9 @@ static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream )
 }
 
 /* be sure that i_ck will be a valid index entry */
-static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream,
+static int AVI_StreamChunkSet( demux_t *p_demux, avi_track_t *p_stream,
                                unsigned int i_ck )
 {
-    demux_sys_t *p_sys = p_demux->p_sys;
-    avi_track_t *p_stream = p_sys->track[i_stream];
-
     p_stream->i_idxposc = i_ck;
     p_stream->i_idxposb = 0;
 
@@ -1890,7 +1934,7 @@ static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream,
         do
         {
             p_stream->i_idxposc++;
-            if( AVI_StreamChunkFind( p_demux, i_stream ) )
+            if( AVI_StreamChunkFind( p_demux, p_stream ) )
             {
                 return VLC_EGENERIC;
             }
@@ -1903,12 +1947,9 @@ static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream,
 
 /* XXX FIXME up to now, we assume that all chunk are one after one */
 static int AVI_StreamBytesSet( demux_t    *p_demux,
-                               unsigned int i_stream,
+                               avi_track_t *p_stream,
                                uint64_t  i_byte )
 {
-    demux_sys_t *p_sys = p_demux->p_sys;
-    avi_track_t *p_stream = p_sys->track[i_stream];
-
     if( ( p_stream->idx.i_size > 0 )
         &&( i_byte < p_stream->idx.p_entry[p_stream->idx.i_size - 1].i_lengthtotal +
                 p_stream->idx.p_entry[p_stream->idx.i_size - 1].i_length ) )
@@ -1951,7 +1992,7 @@ static int AVI_StreamBytesSet( demux_t    *p_demux,
         do
         {
             p_stream->i_idxposc++;
-            if( AVI_StreamChunkFind( p_demux, i_stream ) )
+            if( AVI_StreamChunkFind( p_demux, p_stream ) )
             {
                 return VLC_EGENERIC;
             }
@@ -1971,35 +2012,28 @@ static int AVI_TrackSeek( demux_t *p_demux,
 {
     demux_sys_t  *p_sys = p_demux->p_sys;
     avi_track_t  *tk = p_sys->track[i_stream];
-
-#define p_stream    p_sys->track[i_stream]
     vlc_tick_t i_oldpts;
 
-    i_oldpts = AVI_GetPTS( p_stream );
+    i_oldpts = AVI_GetPTS( tk );
 
-    if( !p_stream->i_samplesize )
+    if( !tk->i_samplesize )
     {
-        if( AVI_StreamChunkSet( p_demux,
-                                i_stream,
-                                AVI_PTSToChunk( p_stream, i_date ) ) )
+        if( AVI_StreamChunkSet( p_demux, tk, AVI_PTSToChunk( tk, i_date ) ) )
         {
             return VLC_EGENERIC;
         }
 
-        if( p_stream->fmt.i_cat == AUDIO_ES )
+        if( tk->fmt.i_cat == AUDIO_ES )
         {
-            unsigned int i;
-            tk->i_blockno = 0;
-            for( i = 0; i < tk->i_idxposc; i++ )
+            if( tk->i_blocksize > 0 )
             {
-                if( tk->i_blocksize > 0 )
-                {
+                tk->i_blockno = tk->i_idxposc;
+            }
+            else
+            {
+                tk->i_blockno = 0;
+                for( unsigned int i = 0; i < tk->i_idxposc; i++ )
                     tk->i_blockno += ( tk->idx.p_entry[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize;
-                }
-                else
-                {
-                    tk->i_blockno++;
-                }
             }
         }
 
@@ -2009,18 +2043,15 @@ static int AVI_TrackSeek( demux_t *p_demux,
                  i_oldpts > i_date ? ">" : "<",
                  i_date );
 
-        if( p_stream->fmt.i_cat == VIDEO_ES )
+        if( tk->fmt.i_cat == VIDEO_ES )
         {
             /* search key frame */
             //if( i_date < i_oldpts || 1 )
             {
-                while( p_stream->i_idxposc > 0 &&
-                   !( p_stream->idx.p_entry[p_stream->i_idxposc].i_flags &
-                                                                AVIIF_KEYFRAME ) )
+                while( tk->i_idxposc > 0 &&
+                   !( tk->idx.p_entry[tk->i_idxposc].i_flags & AVIIF_KEYFRAME ) )
                 {
-                    if( AVI_StreamChunkSet( p_demux,
-                                            i_stream,
-                                            p_stream->i_idxposc - 1 ) )
+                    if( AVI_StreamChunkSet( p_demux, tk, tk->i_idxposc - 1 ) )
                     {
                         return VLC_EGENERIC;
                     }
@@ -2029,13 +2060,10 @@ static int AVI_TrackSeek( demux_t *p_demux,
 #if 0
             else
             {
-                while( p_stream->i_idxposc < p_stream->idx.i_size &&
-                        !( p_stream->idx.p_entry[p_stream->i_idxposc].i_flags &
-                                                                AVIIF_KEYFRAME ) )
+                while( tk->i_idxposc < tk->idx.i_size &&
+                        !( tk->idx.p_entry[tk->i_idxposc].i_flags & AVIIF_KEYFRAME ) )
                 {
-                    if( AVI_StreamChunkSet( p_demux,
-                                            i_stream,
-                                            p_stream->i_idxposc + 1 ) )
+                    if( AVI_StreamChunkSet( p_demux, tk, tk->i_idxposc + 1 ) )
                     {
                         return VLC_EGENERIC;
                     }
@@ -2046,23 +2074,27 @@ static int AVI_TrackSeek( demux_t *p_demux,
     }
     else
     {
-        if( AVI_StreamBytesSet( p_demux,
-                                i_stream,
-                                AVI_PTSToByte( p_stream, i_date ) ) )
+        if( AVI_StreamBytesSet( p_demux, tk, AVI_PTSToByte( tk, i_date ) ) )
         {
             return VLC_EGENERIC;
         }
     }
     return VLC_SUCCESS;
-#undef p_stream
 }
 
 /****************************************************************************
  * Return true if it's a key frame
  ****************************************************************************/
-static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
+static int AVI_GetKeyFlag( const avi_track_t *tk, const uint8_t *p_byte )
 {
-    switch( i_fourcc )
+    if( tk->is_qnap )
+    {
+        const uint8_t *p = p_byte;
+        if( IsQNAPCodec(VLC_FOURCC(p[0],p[1],p[2],p[3])) )
+            return p[4] & 0x01 ? AVIIF_KEYFRAME : 0;
+    }
+
+    switch( tk->fmt.i_codec )
     {
         case VLC_CODEC_DIV1:
             /* we have:
@@ -2273,21 +2305,32 @@ static void avi_index_Clean( avi_index_t *p_index )
 {
     free( p_index->p_entry );
 }
-static void avi_index_Append( avi_index_t *p_index, uint64_t *pi_last_pos,
-                              avi_entry_t *p_entry )
+#define MAX_INDEX_ENTRIES __MIN(SIZE_MAX/sizeof(avi_entry_t), UINT32_MAX)
+#define INDEX_EXTENT 16384
+static int64_t avi_index_Append( avi_index_t *p_index, uint64_t *pi_last_pos,
+                                 avi_entry_t *p_entry )
 {
     /* Update last chunk position */
     if( *pi_last_pos < p_entry->i_pos )
          *pi_last_pos = p_entry->i_pos;
 
+    if( p_index->i_size == MAX_INDEX_ENTRIES )
+        return -1;
+
     /* add the entry */
     if( p_index->i_size >= p_index->i_max )
     {
-        p_index->i_max += 16384;
+        if( MAX_INDEX_ENTRIES - INDEX_EXTENT > p_index->i_max )
+            p_index->i_max += INDEX_EXTENT;
+        else
+            p_index->i_max = MAX_INDEX_ENTRIES;
         p_index->p_entry = realloc_or_free( p_index->p_entry,
-                                            p_index->i_max * sizeof( *p_index->p_entry ) );
+                                            p_index->i_max * sizeof(avi_entry_t) );
         if( !p_index->p_entry )
-            return;
+        {
+            avi_index_Init( p_index );
+            return -1;
+        }
     }
     /* calculate cumulate length */
     if( p_index->i_size > 0 )
@@ -2302,6 +2345,7 @@ static void avi_index_Append( avi_index_t *p_index, uint64_t *pi_last_pos,
     }
 
     p_index->p_entry[p_index->i_size++] = *p_entry;
+    return p_index->i_size - 1;
 }
 
 static int AVI_IndexFind_idx1( demux_t *p_demux,
@@ -2483,7 +2527,6 @@ static void AVI_IndexLoad_indx( demux_t *p_demux,
         avi_chunk_list_t    *p_strl;
         avi_chunk_indx_t    *p_indx;
 
-#define p_stream  p_sys->track[i_stream]
         p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream, true );
         p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
 
@@ -2522,7 +2565,6 @@ static void AVI_IndexLoad_indx( demux_t *p_demux,
         {
             msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
         }
-#undef p_stream
     }
 }
 
@@ -2576,7 +2618,7 @@ static void AVI_IndexLoad( demux_t *p_demux )
             b_key = p_index->p_entry[j].i_flags & AVIIF_KEYFRAME;
         if( !b_key )
         {
-            msg_Err( p_demux, "no key frame set for track %u", i );
+            msg_Warn( p_demux, "no key frame set for track %u", i );
             for( unsigned j = 0; j < p_index->i_size; j++ )
                 p_index->p_entry[j].i_flags |= AVIIF_KEYFRAME;
         }
@@ -2657,7 +2699,7 @@ static void AVI_IndexCreate( demux_t *p_demux )
 
             avi_entry_t index;
             index.i_id      = pk.i_fourcc;
-            index.i_flags   = AVI_GetKeyFlag(tk->fmt.i_codec, pk.i_peek);
+            index.i_flags   = AVI_GetKeyFlag(tk, pk.i_peek);
             index.i_pos     = pk.i_pos;
             index.i_length  = pk.i_size;
             index.i_lengthtotal = pk.i_size;


=====================================
modules/demux/avi/bitmapinfoheader.h
=====================================
@@ -188,7 +188,7 @@ static inline int ParseBitmapInfoHeader( VLC_BITMAPINFOHEADER *p_bih, size_t i_b
     }
     else /* Compressed codecs */
     {
-        fmt->i_codec = p_bih->biCompression;
+        fmt->i_codec = vlc_fourcc_GetCodec( VIDEO_ES, p_bih->biCompression );
 
         /* Copy extradata if any */
         if( i_bihextra > 0 )


=====================================
modules/demux/avi/libavi.c
=====================================
@@ -195,7 +195,7 @@ static int AVI_ChunkRead_list( stream_t *s, avi_chunk_t *p_container )
 #endif
     msg_Dbg( s, "<list \'%4.4s\'>", (char*)&p_container->list.i_type );
 
-    union  avi_chunk_u **pp_append = &p_container->common.p_first;
+    avi_chunk_t **pp_append = &p_container->common.p_first;
     for( ; ; )
     {
         p_chk = calloc( 1, sizeof( avi_chunk_t ) );
@@ -259,7 +259,7 @@ int AVI_ChunkFetchIndexes( stream_t *s, avi_chunk_t *p_riff )
     if ( !b_seekable || vlc_stream_Seek( s, i_indexpos ) )
         return VLC_EGENERIC;
 
-    union  avi_chunk_u **pp_append = &p_riff->common.p_first;
+    avi_chunk_t **pp_append = &p_riff->common.p_first;
     for( ; ; )
     {
         p_chk = calloc( 1, sizeof( avi_chunk_t ) );
@@ -1128,7 +1128,7 @@ int AVI_ChunkReadRoot( stream_t *s, avi_chunk_t *p_root )
 
     p_list->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );
 
-    union  avi_chunk_u **pp_append = &p_root->common.p_first;
+    avi_chunk_t **pp_append = &p_root->common.p_first;
     for( ; ; )
     {
         p_chk = calloc( 1, sizeof( avi_chunk_t ) );


=====================================
modules/demux/avi/libavi.h
=====================================
@@ -37,17 +37,19 @@
                                         /* the keyframe flag isn't a true flag */
                                         /* but have to be verified */
 
+typedef union avi_chunk_u avi_chunk_t;
+
 #define AVI_CHUNK_COMMON           \
     vlc_fourcc_t i_chunk_fourcc;   \
     uint64_t i_chunk_size;         \
     uint64_t i_chunk_pos;          \
-    union  avi_chunk_u *p_next;    \
-    union  avi_chunk_u *p_father;  \
-    union  avi_chunk_u *p_first;
+    avi_chunk_t *p_next;           \
+    avi_chunk_t *p_father;         \
+    avi_chunk_t *p_first;
 
 #define AVI_CHUNK( p_chk ) (avi_chunk_t*)(p_chk)
 
-typedef struct idx1_entry_s
+typedef struct
 {
     vlc_fourcc_t i_fourcc;
     uint32_t i_flags;
@@ -56,18 +58,18 @@ typedef struct idx1_entry_s
 
 } idx1_entry_t;
 
-typedef struct avi_chunk_common_s
+typedef struct
 {
     AVI_CHUNK_COMMON
 } avi_chunk_common_t;
 
-typedef struct avi_chunk_list_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     vlc_fourcc_t i_type;
 } avi_chunk_list_t;
 
-typedef struct avi_chunk_idx1_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     unsigned int i_entry_count;
@@ -76,7 +78,7 @@ typedef struct avi_chunk_idx1_s
 
 } avi_chunk_idx1_t;
 
-typedef struct avi_chunk_avih_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     uint32_t i_microsecperframe;
@@ -96,7 +98,7 @@ typedef struct avi_chunk_avih_s
     uint32_t i_length;
 } avi_chunk_avih_t;
 
-typedef struct avi_chunk_strh_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     vlc_fourcc_t i_type;
@@ -113,21 +115,21 @@ typedef struct avi_chunk_strh_s
     uint32_t i_samplesize;
 } avi_chunk_strh_t;
 
-typedef struct avi_chunk_strf_auds_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     int             i_cat;
     WAVEFORMATEX    *p_wf;
 } avi_chunk_strf_auds_t;
 
-typedef struct avi_chunk_strf_vids_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     int                     i_cat;
     VLC_BITMAPINFOHEADER    *p_bih;
 } avi_chunk_strf_vids_t;
 
-typedef union avi_chunk_strf_u
+typedef union
 {
     avi_chunk_strf_auds_t   auds;
     avi_chunk_strf_vids_t   vids;
@@ -138,13 +140,13 @@ typedef union avi_chunk_strf_u
     }                       common;
 } avi_chunk_strf_t;
 
-typedef struct avi_chunk_strd_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     uint8_t  *p_data;
 } avi_chunk_strd_t;
 
-typedef struct avi_chunk_vprp_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     uint32_t i_video_format_token;
@@ -170,7 +172,7 @@ typedef struct avi_chunk_vprp_s
 
 } avi_chunk_vprp_t;
 
-typedef struct avi_chunk_dmlh_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     uint32_t dwTotalFrames;
@@ -204,7 +206,7 @@ typedef struct
     uint32_t i_duration;
 } indx_super_entry_t;
 
-typedef struct avi_chunk_indx_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     int16_t  i_longsperentry;
@@ -223,14 +225,14 @@ typedef struct avi_chunk_indx_s
     } idx;
 } avi_chunk_indx_t;
 
-typedef struct avi_chunk_STRING_s
+typedef struct
 {
     AVI_CHUNK_COMMON
     char *p_type;
     char *p_str;
 } avi_chunk_STRING_t;
 
-typedef union avi_chunk_u
+union avi_chunk_u
 {
     avi_chunk_common_t  common;
     avi_chunk_list_t    list;
@@ -242,7 +244,7 @@ typedef union avi_chunk_u
     avi_chunk_vprp_t    vprp;
     avi_chunk_indx_t    indx;
     avi_chunk_STRING_t  strz;
-} avi_chunk_t;
+};
 
 /****************************************************************************
  * Stream(input) access functions
@@ -368,3 +370,14 @@ int     AVI_ChunkFetchIndexes( stream_t *, avi_chunk_t *p_riff );
 #define FOURCC_dvsl         VLC_FOURCC('d','v','s','l')
 #define FOURCC_dv25         VLC_FOURCC('d','v','2','5')
 #define FOURCC_dv50         VLC_FOURCC('d','v','5','0')
+
+/* QNap */
+#define QNAP_FCC_w264       VLC_FOURCC('w','2','6','4')
+#define QNAP_FCC_q264       VLC_FOURCC('q','2','6','4')
+#define QNAP_FCC_Q264       VLC_FOURCC('Q','2','6','4')
+#define QNAP_FCC_wMP4       VLC_FOURCC('w','M','P','4')
+#define QNAP_FCC_qMP4       VLC_FOURCC('q','M','P','4')
+#define QNAP_FCC_QMP4       VLC_FOURCC('Q','M','P','4')
+#define QNAP_FCC_wIVG       VLC_FOURCC('w','I','V','G')
+#define QNAP_FCC_qIVG       VLC_FOURCC('q','I','V','G')
+#define QNAP_FCC_QIVG       VLC_FOURCC('Q','I','V','G')



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/81d75d3010a3a051c4dba2d42a3f4d3dc065b404...0acdec00f7c7f1b77776cd931356b2fec5d6a340

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/81d75d3010a3a051c4dba2d42a3f4d3dc065b404...0acdec00f7c7f1b77776cd931356b2fec5d6a340
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list