|
|
|
@ -44,6 +44,8 @@ typedef struct Mpeg1Context { |
|
|
|
|
int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ |
|
|
|
|
int repeat_field; /* true if we must repeat the field */ |
|
|
|
|
AVPanScan pan_scan; /**< some temporary storage for the panscan */ |
|
|
|
|
uint8_t *a53_caption; |
|
|
|
|
int a53_caption_size; |
|
|
|
|
int slice_count; |
|
|
|
|
int save_aspect_info; |
|
|
|
|
int save_width, save_height, save_progressive_seq; |
|
|
|
@ -1529,6 +1531,14 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
memcpy(pan_scan->data, &s1->pan_scan, sizeof(s1->pan_scan)); |
|
|
|
|
|
|
|
|
|
if (s1->a53_caption) { |
|
|
|
|
AVFrameSideData *sd = av_frame_new_side_data( |
|
|
|
|
&s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC, |
|
|
|
|
s1->a53_caption_size); |
|
|
|
|
if (sd) |
|
|
|
|
memcpy(sd->data, s1->a53_caption, s1->a53_caption_size); |
|
|
|
|
av_freep(&s1->a53_caption); |
|
|
|
|
} |
|
|
|
|
if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME)) |
|
|
|
|
ff_thread_finish_setup(avctx); |
|
|
|
|
} else { // second field
|
|
|
|
@ -2038,6 +2048,60 @@ static int vcr2_init_sequence(AVCodecContext *avctx) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int mpeg_decode_a53_cc(AVCodecContext *avctx, |
|
|
|
|
const uint8_t *p, int buf_size) |
|
|
|
|
{ |
|
|
|
|
Mpeg1Context *s1 = avctx->priv_data; |
|
|
|
|
|
|
|
|
|
if (buf_size >= 6 && |
|
|
|
|
p[0] == 'G' && p[1] == 'A' && p[2] == '9' && p[3] == '4' && |
|
|
|
|
p[4] == 3 && (p[5] & 0x40)) { |
|
|
|
|
/* extract A53 Part 4 CC data */ |
|
|
|
|
int cc_count = p[5] & 0x1f; |
|
|
|
|
if (cc_count > 0 && buf_size >= 7 + cc_count * 3) { |
|
|
|
|
av_freep(&s1->a53_caption); |
|
|
|
|
s1->a53_caption_size = cc_count * 3; |
|
|
|
|
s1->a53_caption = av_malloc(s1->a53_caption_size); |
|
|
|
|
if (s1->a53_caption) { |
|
|
|
|
memcpy(s1->a53_caption, p + 7, s1->a53_caption_size); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 1; |
|
|
|
|
} else if (buf_size >= 11 && |
|
|
|
|
p[0] == 'C' && p[1] == 'C' && p[2] == 0x01 && p[3] == 0xf8) { |
|
|
|
|
/* extract DVD CC data */ |
|
|
|
|
int cc_count = 0; |
|
|
|
|
int i; |
|
|
|
|
// There is a caption count field in the data, but it is often
|
|
|
|
|
// incorect. So count the number of captions present.
|
|
|
|
|
for (i = 5; i + 6 <= buf_size && ((p[i] & 0xfe) == 0xfe); i += 6) |
|
|
|
|
cc_count++; |
|
|
|
|
// Transform the DVD format into A53 Part 4 format
|
|
|
|
|
if (cc_count > 0) { |
|
|
|
|
av_freep(&s1->a53_caption); |
|
|
|
|
s1->a53_caption_size = cc_count * 6; |
|
|
|
|
s1->a53_caption = av_malloc(s1->a53_caption_size); |
|
|
|
|
if (s1->a53_caption) { |
|
|
|
|
uint8_t field1 = !!(p[4] & 0x80); |
|
|
|
|
uint8_t *cap = s1->a53_caption; |
|
|
|
|
p += 5; |
|
|
|
|
for (i = 0; i < cc_count; i++) { |
|
|
|
|
cap[0] = (p[0] == 0xff && field1) ? 0xfc : 0xfd; |
|
|
|
|
cap[1] = p[1]; |
|
|
|
|
cap[2] = p[2]; |
|
|
|
|
cap[3] = (p[3] == 0xff && !field1) ? 0xfc : 0xfd; |
|
|
|
|
cap[4] = p[4]; |
|
|
|
|
cap[5] = p[5]; |
|
|
|
|
cap += 6; |
|
|
|
|
p += 6; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void mpeg_decode_user_data(AVCodecContext *avctx, |
|
|
|
|
const uint8_t *p, int buf_size) |
|
|
|
|
{ |
|
|
|
@ -2057,6 +2121,8 @@ static void mpeg_decode_user_data(AVCodecContext *avctx, |
|
|
|
|
return; |
|
|
|
|
avctx->dtg_active_format = p[0] & 0x0f; |
|
|
|
|
} |
|
|
|
|
} else if (mpeg_decode_a53_cc(avctx, p, buf_size)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2402,6 +2468,7 @@ static av_cold int mpeg_decode_end(AVCodecContext *avctx) |
|
|
|
|
|
|
|
|
|
if (s->mpeg_enc_ctx_allocated) |
|
|
|
|
ff_MPV_common_end(&s->mpeg_enc_ctx); |
|
|
|
|
av_freep(&s->a53_caption); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|