/*****************************************************************************
- * Copyright © 2010-2011 VideoLAN
+ * Copyright © 2010-2014 VideoLAN
*
* Authors: Jean-Baptiste Kempf <jb@videolan.org>
*
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
-#include <limits.h>
+#ifndef H264_NAL_H
+# define H264_NAL_H
-/* Parse the SPS/PPS Metadata and convert it to annex b format */
-static int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
- uint32_t i_buf_size, uint8_t *p_out_buf,
- uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
- uint32_t *p_nal_size)
-{
- int i_profile;
- uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
- unsigned int i_loop_end;
-
- /* */
- if( i_data_size < 7 )
- {
- msg_Err( p_dec, "Input Metadata too small" );
- return VLC_ENOMEM;
- }
-
- /* Read infos in first 6 bytes */
- i_profile = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
- if (p_nal_size)
- *p_nal_size = (p_buf[4] & 0x03) + 1;
- p_buf += 5;
- i_data_size -= 5;
-
- for ( unsigned int j = 0; j < 2; j++ )
- {
- /* First time is SPS, Second is PPS */
- if( i_data_size < 1 )
- {
- msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
- i_data_size );
- return VLC_ENOMEM;
- }
- i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
- p_buf++; i_data_size--;
-
- for ( unsigned int i = 0; i < i_loop_end; i++)
- {
- if( i_data_size < 2 )
- {
- msg_Err( p_dec, "SPS is too small %u", i_data_size );
- return VLC_ENOMEM;
- }
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
- i_nal_size = (p_buf[0] << 8) | p_buf[1];
- p_buf += 2;
- i_data_size -= 2;
+# include <vlc_common.h>
+# include <vlc_codec.h>
- if( i_data_size < i_nal_size )
- {
- msg_Err( p_dec, "SPS size does not match NAL specified size %u",
- i_data_size );
- return VLC_ENOMEM;
- }
- if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
- {
- msg_Err( p_dec, "Output SPS/PPS buffer too small" );
- return VLC_ENOMEM;
- }
+#define PROFILE_H264_BASELINE 66
+#define PROFILE_H264_MAIN 77
+#define PROFILE_H264_EXTENDED 88
+#define PROFILE_H264_HIGH 100
+#define PROFILE_H264_HIGH_10 110
+#define PROFILE_H264_HIGH_422 122
+#define PROFILE_H264_HIGH_444 144
+#define PROFILE_H264_HIGH_444_PREDICTIVE 244
- p_out_buf[i_sps_pps_size++] = 0;
- p_out_buf[i_sps_pps_size++] = 0;
- p_out_buf[i_sps_pps_size++] = 0;
- p_out_buf[i_sps_pps_size++] = 1;
+#define PROFILE_H264_CAVLC_INTRA 44
+#define PROFILE_H264_SVC_BASELINE 83
+#define PROFILE_H264_SVC_HIGH 86
+#define PROFILE_H264_MVC_STEREO_HIGH 128
+#define PROFILE_H264_MVC_MULTIVIEW_HIGH 118
- memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
- i_sps_pps_size += i_nal_size;
-
- p_buf += i_nal_size;
- i_data_size -= i_nal_size;
- }
- }
+/* Parse the SPS/PPS Metadata and convert it to annex b format */
+int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
+ uint32_t i_buf_size, uint8_t *p_out_buf,
+ uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
+ uint32_t *p_nal_size);
- *p_sps_pps_size = i_sps_pps_size;
+/* Convert H.264 NAL format to annex b in-place */
+struct H264ConvertState {
+ uint32_t nal_len;
+ uint32_t nal_pos;
+};
- return VLC_SUCCESS;
-}
+void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
+ size_t i_nal_size,
+ struct H264ConvertState *state );
-/* Convert H.264 NAL format to annex b in-place */
-static void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
- size_t i_nal_size )
-{
- if( i_nal_size < 3 || i_nal_size > 4 )
- return;
+/* Get level and Profile */
+bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
+ size_t *p_level, size_t *p_nal_size);
- /* This only works for NAL sizes 3-4 */
- while( i_len >= i_nal_size )
- {
- uint32_t nal_len = 0;
- for( unsigned int i = 0; i < i_nal_size; i++ ) {
- nal_len = (nal_len << 8) | p_buf[i];
- p_buf[i] = 0;
- }
- p_buf[i_nal_size - 1] = 1;
- if( nal_len > INT_MAX || nal_len > (unsigned int) i_len )
- break;
- p_buf += nal_len + i_nal_size;
- i_len -= nal_len + i_nal_size;
- }
-}
+#endif /* H264_NAL_H */