@ -62,6 +62,13 @@
# define A53_MAX_CC_COUNT 2000
# define A53_MAX_CC_COUNT 2000
enum Mpeg2ClosedCaptionsFormat {
CC_FORMAT_AUTO ,
CC_FORMAT_A53_PART4 ,
CC_FORMAT_SCTE20 ,
CC_FORMAT_DVD
} ;
typedef struct Mpeg1Context {
typedef struct Mpeg1Context {
MpegEncContext mpeg_enc_ctx ;
MpegEncContext mpeg_enc_ctx ;
int mpeg_enc_ctx_allocated ; /* true if decoding context allocated */
int mpeg_enc_ctx_allocated ; /* true if decoding context allocated */
@ -70,6 +77,7 @@ typedef struct Mpeg1Context {
AVStereo3D stereo3d ;
AVStereo3D stereo3d ;
int has_stereo3d ;
int has_stereo3d ;
AVBufferRef * a53_buf_ref ;
AVBufferRef * a53_buf_ref ;
enum Mpeg2ClosedCaptionsFormat cc_format ;
uint8_t afd ;
uint8_t afd ;
int has_afd ;
int has_afd ;
int slice_count ;
int slice_count ;
@ -1903,12 +1911,27 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
return 0 ;
return 0 ;
}
}
static void mpeg_set_cc_format ( AVCodecContext * avctx , enum Mpeg2ClosedCaptionsFormat format ,
const char * label )
{
Mpeg1Context * s1 = avctx - > priv_data ;
av_assert2 ( format ! = CC_FORMAT_AUTO ) ;
if ( ! s1 - > cc_format ) {
s1 - > cc_format = format ;
av_log ( avctx , AV_LOG_DEBUG , " CC: first seen substream is %s format \n " , label ) ;
}
}
static int mpeg_decode_a53_cc ( AVCodecContext * avctx ,
static int mpeg_decode_a53_cc ( AVCodecContext * avctx ,
const uint8_t * p , int buf_size )
const uint8_t * p , int buf_size )
{
{
Mpeg1Context * s1 = avctx - > priv_data ;
Mpeg1Context * s1 = avctx - > priv_data ;
if ( buf_size > = 6 & &
if ( ( ! s1 - > cc_format | | s1 - > cc_format = = CC_FORMAT_A53_PART4 ) & &
buf_size > = 6 & &
p [ 0 ] = = ' G ' & & p [ 1 ] = = ' A ' & & p [ 2 ] = = ' 9 ' & & p [ 3 ] = = ' 4 ' & &
p [ 0 ] = = ' G ' & & p [ 1 ] = = ' A ' & & p [ 2 ] = = ' 9 ' & & p [ 3 ] = = ' 4 ' & &
p [ 4 ] = = 3 & & ( p [ 5 ] & 0x40 ) ) {
p [ 4 ] = = 3 & & ( p [ 5 ] & 0x40 ) ) {
/* extract A53 Part 4 CC data */
/* extract A53 Part 4 CC data */
@ -1927,9 +1950,11 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
memcpy ( s1 - > a53_buf_ref - > data + old_size , p + 7 , cc_count * UINT64_C ( 3 ) ) ;
memcpy ( s1 - > a53_buf_ref - > data + old_size , p + 7 , cc_count * UINT64_C ( 3 ) ) ;
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
mpeg_set_cc_format ( avctx , CC_FORMAT_A53_PART4 , " A/53 Part 4 " ) ;
}
}
return 1 ;
return 1 ;
} else if ( buf_size > = 2 & &
} else if ( ( ! s1 - > cc_format | | s1 - > cc_format = = CC_FORMAT_SCTE20 ) & &
buf_size > = 2 & &
p [ 0 ] = = 0x03 & & ( p [ 1 ] & 0x7f ) = = 0x01 ) {
p [ 0 ] = = 0x03 & & ( p [ 1 ] & 0x7f ) = = 0x01 ) {
/* extract SCTE-20 CC data */
/* extract SCTE-20 CC data */
GetBitContext gb ;
GetBitContext gb ;
@ -1973,10 +1998,13 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
cap + = 3 ;
cap + = 3 ;
}
}
}
}
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
mpeg_set_cc_format ( avctx , CC_FORMAT_SCTE20 , " SCTE-20 " ) ;
}
}
return 1 ;
return 1 ;
} else if ( buf_size > = 11 & &
} else if ( ( ! s1 - > cc_format | | s1 - > cc_format = = CC_FORMAT_DVD ) & &
buf_size > = 11 & &
p [ 0 ] = = ' C ' & & p [ 1 ] = = ' C ' & & p [ 2 ] = = 0x01 & & p [ 3 ] = = 0xf8 ) {
p [ 0 ] = = ' C ' & & p [ 1 ] = = ' C ' & & p [ 2 ] = = 0x01 & & p [ 3 ] = = 0xf8 ) {
/* extract DVD CC data
/* extract DVD CC data
*
*
@ -2033,7 +2061,9 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
p + = 6 ;
p + = 6 ;
}
}
}
}
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
avctx - > properties | = FF_CODEC_PROPERTY_CLOSED_CAPTIONS ;
mpeg_set_cc_format ( avctx , CC_FORMAT_DVD , " DVD " ) ;
}
}
return 1 ;
return 1 ;
}
}
@ -2598,11 +2628,39 @@ const FFCodec ff_mpeg1video_decoder = {
} ,
} ,
} ;
} ;
# define M2V_OFFSET(x) offsetof(Mpeg1Context, x)
# define M2V_PARAM AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption mpeg2video_options [ ] = {
{ " cc_format " , " extract a specific Closed Captions format " ,
M2V_OFFSET ( cc_format ) , AV_OPT_TYPE_INT , { . i64 = CC_FORMAT_AUTO } ,
CC_FORMAT_AUTO , CC_FORMAT_DVD , M2V_PARAM , . unit = " cc_format " } ,
{ " auto " , " pick first seen CC substream " , 0 , AV_OPT_TYPE_CONST ,
{ . i64 = CC_FORMAT_AUTO } , . flags = M2V_PARAM , . unit = " cc_format " } ,
{ " a53 " , " pick A/53 Part 4 CC substream " , 0 , AV_OPT_TYPE_CONST ,
{ . i64 = CC_FORMAT_A53_PART4 } , . flags = M2V_PARAM , . unit = " cc_format " } ,
{ " scte20 " , " pick SCTE-20 CC substream " , 0 , AV_OPT_TYPE_CONST ,
{ . i64 = CC_FORMAT_SCTE20 } , . flags = M2V_PARAM , . unit = " cc_format " } ,
{ " dvd " , " pick DVD CC substream " , 0 , AV_OPT_TYPE_CONST ,
{ . i64 = CC_FORMAT_DVD } , . flags = M2V_PARAM , . unit = " cc_format " } ,
{ NULL }
} ;
static const AVClass mpeg2video_class = {
. class_name = " MPEG-2 video " ,
. item_name = av_default_item_name ,
. option = mpeg2video_options ,
. version = LIBAVUTIL_VERSION_INT ,
. category = AV_CLASS_CATEGORY_DECODER ,
} ;
const FFCodec ff_mpeg2video_decoder = {
const FFCodec ff_mpeg2video_decoder = {
. p . name = " mpeg2video " ,
. p . name = " mpeg2video " ,
CODEC_LONG_NAME ( " MPEG-2 video " ) ,
CODEC_LONG_NAME ( " MPEG-2 video " ) ,
. p . type = AVMEDIA_TYPE_VIDEO ,
. p . type = AVMEDIA_TYPE_VIDEO ,
. p . id = AV_CODEC_ID_MPEG2VIDEO ,
. p . id = AV_CODEC_ID_MPEG2VIDEO ,
. p . priv_class = & mpeg2video_class ,
. priv_data_size = sizeof ( Mpeg1Context ) ,
. priv_data_size = sizeof ( Mpeg1Context ) ,
. init = mpeg_decode_init ,
. init = mpeg_decode_init ,
. close = mpeg_decode_end ,
. close = mpeg_decode_end ,