]> git.sesse.net Git - vlc/blobdiff - modules/packetizer/packetizer_helper.h
MKV: fix ATRAC3 playback
[vlc] / modules / packetizer / packetizer_helper.h
index 33e9c77cda035d04d4a87797199d4da97201436d..33754b7d04057d1c245b26929e73d1b1f5f283b1 100644 (file)
@@ -1,24 +1,24 @@
 /*****************************************************************************
- * packetizer.h: Packetizer helpers
+ * packetizer_helper.h: Packetizer helpers
  *****************************************************************************
  * Copyright (C) 2009 Laurent Aimar
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
  *
- * 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
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #ifndef _PACKETIZER_H
 enum
 {
     STATE_NOSYNC,
-    STATE_NEXT_SYNC
+    STATE_SYNC,
+    STATE_HEADER,
+    STATE_NEXT_SYNC,
+    STATE_GET_DATA,
+    STATE_SEND_DATA
 };
 
 typedef void (*packetizer_reset_t)( void *p_private, bool b_broken );
@@ -41,6 +45,7 @@ typedef struct
     int i_state;
     block_bytestream_t bytestream;
     size_t i_offset;
+    bool   b_flushing;
 
     int i_startcode;
     const uint8_t *p_startcode;
@@ -48,6 +53,8 @@ typedef struct
     int i_au_prepend;
     const uint8_t *p_au_prepend;
 
+    unsigned i_au_min_size;
+
     void *p_private;
     packetizer_reset_t    pf_reset;
     packetizer_parse_t    pf_parse;
@@ -58,17 +65,20 @@ typedef struct
 static inline void packetizer_Init( packetizer_t *p_pack,
                                     const uint8_t *p_startcode, int i_startcode,
                                     const uint8_t *p_au_prepend, int i_au_prepend,
+                                    unsigned i_au_min_size,
                                     packetizer_reset_t pf_reset,
                                     packetizer_parse_t pf_parse,
                                     packetizer_validate_t pf_validate,
                                     void *p_private )
 {
     p_pack->i_state = STATE_NOSYNC;
-    p_pack->bytestream = block_BytestreamInit();
+    block_BytestreamInit( &p_pack->bytestream );
     p_pack->i_offset = 0;
+    p_pack->b_flushing = false;
 
     p_pack->i_au_prepend = i_au_prepend;
     p_pack->p_au_prepend = p_au_prepend;
+    p_pack->i_au_min_size = i_au_min_size;
 
     p_pack->i_startcode = i_startcode;
     p_pack->p_startcode = p_startcode;
@@ -88,7 +98,7 @@ static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_
     if( !pp_block || !*pp_block )
         return NULL;
 
-    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
+    if( unlikely( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) )
     {
         const bool b_broken = ( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED ) != 0;
         if( b_broken )
@@ -134,14 +144,26 @@ static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_
             /* Find the next startcode */
             if( block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
                                                p_pack->p_startcode, p_pack->i_startcode ) )
-                return NULL; /* Need more data */
+            {
+                if( !p_pack->b_flushing || !p_pack->bytestream.p_chain )
+                    return NULL; /* Need more data */
+
+                /* When flusing and we don't find a startcode, suppose that
+                 * the data extend up to the end */
+                block_ChainProperties( p_pack->bytestream.p_chain,
+                                       NULL, &p_pack->i_offset, NULL );
+                p_pack->i_offset -= p_pack->bytestream .i_offset;
+
+                if( p_pack->i_offset <= (size_t)p_pack->i_startcode )
+                    return NULL;
+            }
 
             block_BytestreamFlush( &p_pack->bytestream );
 
             /* Get the new fragment and set the pts/dts */
             block_t *p_block_bytestream = p_pack->bytestream.p_block;
 
-            p_pic = block_New( p_dec, p_pack->i_offset + p_pack->i_au_prepend );
+            p_pic = block_Alloc( p_pack->i_offset + p_pack->i_au_prepend );
             p_pic->i_pts = p_block_bytestream->i_pts;
             p_pic->i_dts = p_block_bytestream->i_dts;
 
@@ -153,11 +175,19 @@ static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_
             p_pack->i_offset = 0;
 
             /* Parse the NAL */
-            p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
-            if( b_used_ts )
+            if( p_pic->i_buffer < p_pack->i_au_min_size )
+            {
+                block_Release( p_pic );
+                p_pic = NULL;
+            }
+            else
             {
-                p_block_bytestream->i_dts = -1;
-                p_block_bytestream->i_pts = -1;
+                p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
+                if( b_used_ts )
+                {
+                    p_block_bytestream->i_dts = VLC_TS_INVALID;
+                    p_block_bytestream->i_pts = VLC_TS_INVALID;
+                }
             }
 
             if( !p_pic )
@@ -182,5 +212,26 @@ static inline block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_
     }
 }
 
+static inline void packetizer_Header( packetizer_t *p_pack,
+                                      const uint8_t *p_header, int i_header )
+{
+    block_t *p_init = block_Alloc( i_header );
+    if( !p_init )
+        return;
+
+    memcpy( p_init->p_buffer, p_header, i_header );
+
+    p_pack->b_flushing = true;
+
+    block_t *p_pic;
+    while( ( p_pic = packetizer_Packetize( p_pack, &p_init ) ) )
+        block_Release( p_pic ); /* Should not happen (only sequence header) */
+
+    p_pack->i_state = STATE_NOSYNC;
+    block_BytestreamEmpty( &p_pack->bytestream );
+    p_pack->i_offset = 0;
+    p_pack->b_flushing = false;
+}
+
 #endif