Commit 61e14f1b authored by Felix Abecassis's avatar Felix Abecassis

h264_nal: add a source file to separate declaration from definition

parent 5d0f6603
...@@ -346,7 +346,7 @@ noinst_HEADERS += \ ...@@ -346,7 +346,7 @@ noinst_HEADERS += \
libomxil_plugin_la_SOURCES = \ libomxil_plugin_la_SOURCES = \
codec/omxil/utils.c codec/omxil/omxil_utils.h \ codec/omxil/utils.c codec/omxil/omxil_utils.h \
codec/h264_nal.h \ codec/h264_nal.c codec/h264_nal.h \
codec/omxil/qcom.c codec/omxil/qcom.h \ codec/omxil/qcom.c codec/omxil/qcom.h \
codec/omxil/omxil.c codec/omxil/omxil.h codec/omxil/omxil_core.c codec/omxil/omxil_core.h \ codec/omxil/omxil.c codec/omxil/omxil.h codec/omxil/omxil_core.c codec/omxil/omxil_core.h \
video_chroma/copy.c video_chroma/copy.c
...@@ -365,7 +365,8 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD) ...@@ -365,7 +365,8 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD)
libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
libmediacodec_plugin_la_SOURCES = codec/omxil/android_mediacodec.c codec/omxil/utils.c \ libmediacodec_plugin_la_SOURCES = codec/omxil/android_mediacodec.c codec/omxil/utils.c \
video_chroma/copy.c codec/omxil/android_opaque.c codec/omxil/android_opaque.h video_chroma/copy.c codec/omxil/android_opaque.c codec/omxil/android_opaque.h \
codec/h264_nal.c codec/h264_nal.h
codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout) codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout)
EXTRA_LTLIBRARIES += libomxil_plugin.la libomxil_vout_plugin.la EXTRA_LTLIBRARIES += libomxil_plugin.la libomxil_vout_plugin.la
...@@ -453,7 +454,7 @@ codec_LTLIBRARIES += $(LTLIBtwolame) ...@@ -453,7 +454,7 @@ codec_LTLIBRARIES += $(LTLIBtwolame)
### Hardware encoders ### ### Hardware encoders ###
libcrystalhd_plugin_la_SOURCES = codec/crystalhd.c codec/h264_nal.h libcrystalhd_plugin_la_SOURCES = codec/crystalhd.c codec/h264_nal.c codec/h264_nal.h
libcrystalhd_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)' libcrystalhd_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(codecdir)'
libcrystalhd_plugin_la_LIBADD = $(LIBS_crystalhd) libcrystalhd_plugin_la_LIBADD = $(LIBS_crystalhd)
EXTRA_LTLIBRARIES += libcrystalhd_plugin.la EXTRA_LTLIBRARIES += libcrystalhd_plugin.la
......
/*****************************************************************************
* Copyright © 2010-2014 VideoLAN
*
* Authors: Jean-Baptiste Kempf <jb@videolan.org>
*
* 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 Lesser General Public License for more details.
*
* 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.
*****************************************************************************/
#include "h264_nal.h"
#include <limits.h>
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;
}
i_nal_size = (p_buf[0] << 8) | p_buf[1];
p_buf += 2;
i_data_size -= 2;
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;
}
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;
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;
}
}
*p_sps_pps_size = i_sps_pps_size;
return VLC_SUCCESS;
}
void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
size_t i_nal_size,
struct H264ConvertState *state )
{
if( i_nal_size < 3 || i_nal_size > 4 )
return;
/* This only works for NAL sizes 3-4 */
while( i_len > 0 )
{
if( state->nal_pos < i_nal_size ) {
unsigned int i;
for( i = 0; state->nal_pos < i_nal_size && i < i_len; i++, state->nal_pos++ ) {
state->nal_len = (state->nal_len << 8) | p_buf[i];
p_buf[i] = 0;
}
if( state->nal_pos < i_nal_size )
return;
p_buf[i - 1] = 1;
p_buf += i;
i_len -= i;
}
if( state->nal_len > INT_MAX )
return;
if( state->nal_len > i_len )
{
state->nal_len -= i_len;
return;
}
else
{
p_buf += state->nal_len;
i_len -= state->nal_len;
state->nal_len = 0;
state->nal_pos = 0;
}
}
}
bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
size_t *p_level, size_t *p_nal_size)
{
uint8_t *p = (uint8_t*)p_fmt->p_extra;
if(!p || !p_fmt->p_extra) return false;
/* Check the profile / level */
if (p_fmt->i_original_fourcc == VLC_FOURCC('a','v','c','1') && p[0] == 1)
{
if (p_fmt->i_extra < 12) return false;
if (p_nal_size) *p_nal_size = 1 + (p[4]&0x03);
if (!(p[5]&0x1f)) return false;
p += 8;
}
else
{
if (p_fmt->i_extra < 8) return false;
if (!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
else if (!p[0] && !p[1] && p[2] == 1) p += 3;
else return false;
}
if ( ((*p++)&0x1f) != 7) return false;
/* Get profile/level out of first SPS */
if (p_profile) *p_profile = p[0];
if (p_level) *p_level = p[2];
return true;
}
/***************************************************************************** /*****************************************************************************
* Copyright © 2010-2011 VideoLAN * Copyright © 2010-2014 VideoLAN
* *
* Authors: Jean-Baptiste Kempf <jb@videolan.org> * Authors: Jean-Baptiste Kempf <jb@videolan.org>
* *
...@@ -18,85 +18,18 @@ ...@@ -18,85 +18,18 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/ *****************************************************************************/
#include <limits.h> # ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include <vlc_common.h>
# include <vlc_codec.h>
/* Parse the SPS/PPS Metadata and convert it to annex b format */ /* 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, 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_buf_size, uint8_t *p_out_buf,
uint32_t i_out_buf_size, uint32_t *p_sps_pps_size, uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
uint32_t *p_nal_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;
}
i_nal_size = (p_buf[0] << 8) | p_buf[1];
p_buf += 2;
i_data_size -= 2;
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;
}
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;
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;
}
}
*p_sps_pps_size = i_sps_pps_size;
return VLC_SUCCESS;
}
/* Convert H.264 NAL format to annex b in-place */ /* Convert H.264 NAL format to annex b in-place */
struct H264ConvertState { struct H264ConvertState {
...@@ -104,73 +37,10 @@ struct H264ConvertState { ...@@ -104,73 +37,10 @@ struct H264ConvertState {
uint32_t nal_pos; uint32_t nal_pos;
}; };
static void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len, void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
size_t i_nal_size, size_t i_nal_size,
struct H264ConvertState *state ) struct H264ConvertState *state );
{
if( i_nal_size < 3 || i_nal_size > 4 )
return;
/* This only works for NAL sizes 3-4 */
while( i_len > 0 )
{
if( state->nal_pos < i_nal_size ) {
unsigned int i;
for( i = 0; state->nal_pos < i_nal_size && i < i_len; i++, state->nal_pos++ ) {
state->nal_len = (state->nal_len << 8) | p_buf[i];
p_buf[i] = 0;
}
if( state->nal_pos < i_nal_size )
return;
p_buf[i - 1] = 1;
p_buf += i;
i_len -= i;
}
if( state->nal_len > INT_MAX )
return;
if( state->nal_len > i_len )
{
state->nal_len -= i_len;
return;
}
else
{
p_buf += state->nal_len;
i_len -= state->nal_len;
state->nal_len = 0;
state->nal_pos = 0;
}
}
}
/* Get level and Profile */ /* Get level and Profile */
static bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_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) size_t *p_level, size_t *p_nal_size);
{
uint8_t *p = (uint8_t*)p_fmt->p_extra;
if(!p || !p_fmt->p_extra) return false;
/* Check the profile / level */
if (p_fmt->i_original_fourcc == VLC_FOURCC('a','v','c','1') && p[0] == 1)
{
if (p_fmt->i_extra < 12) return false;
if (p_nal_size) *p_nal_size = 1 + (p[4]&0x03);
if (!(p[5]&0x1f)) return false;
p += 8;
}
else
{
if (p_fmt->i_extra < 8) return false;
if (!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
else if (!p[0] && !p[1] && p[2] == 1) p += 3;
else return false;
}
if ( ((*p++)&0x1f) != 7) return false;
/* Get profile/level out of first SPS */
if (p_profile) *p_profile = p[0];
if (p_level) *p_level = p[2];
return true;
}
...@@ -2,7 +2,7 @@ SOURCES_packetizer_copy = copy.c ...@@ -2,7 +2,7 @@ SOURCES_packetizer_copy = copy.c
SOURCES_packetizer_mpegvideo = mpegvideo.c SOURCES_packetizer_mpegvideo = mpegvideo.c
SOURCES_packetizer_mpeg4video = mpeg4video.c SOURCES_packetizer_mpeg4video = mpeg4video.c
SOURCES_packetizer_mpeg4audio = mpeg4audio.c SOURCES_packetizer_mpeg4audio = mpeg4audio.c
SOURCES_packetizer_h264 = h264.c SOURCES_packetizer_h264 = h264.c ../codec/h264_nal.c ../codec/h264_nal.h
SOURCES_packetizer_vc1 = vc1.c SOURCES_packetizer_vc1 = vc1.c
SOURCES_packetizer_mlp = mlp.c SOURCES_packetizer_mlp = mlp.c
SOURCES_packetizer_dirac = dirac.c SOURCES_packetizer_dirac = dirac.c
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment