[Libav-user] MPEG1-2 CEA-608 CC (subtitle) decoding fails for interlaced content
Eric Jong
ericdejong_nospam10 at gmx.net
Wed Nov 28 17:08:37 EET 2018
Here is an example:
.ts file: https://www.dropbox.com/s/iu8qec0pcng6hv0/TestVid.ts?dl=0
Expected output is both field 1 and field 2,
but only field 2 is shown in output. When I modify the libav source I
do get field 1 and field 2 with the proper data!
// VERY SIMPLE EXAMPLE, NO ERROR CHECKING!
int video_stream_idx = -1;
AVPacket pkt;
AVCodecContext* video_dec_ctx = NULL;
AVFrame* frame = NULL;
int video_frame_count = 0;
char CChar(unsigned char ch) {
ch &= 0x7F;
return (ch < ' ') ? ' ' : ch;
}
static int decode_packet() {
int i,j,cc_valid,cc_type, ret = 0, decoded;
unsigned char data;
decoded = pkt.size;
if (pkt.stream_index == video_stream_idx) {
avcodec_send_packet(video_dec_ctx, &pkt);
do
{
if ((ret = avcodec_receive_frame(video_dec_ctx, frame)) == 0)
{
AVFrameSideData* side_data = frame->side_data[0];
while (frame->nb_side_data--)
{
for (i = 0; i < frame->nb_side_data; i++)
if (frame->side_data[i]->type == AV_FRAME_DATA_A53_CC)
{
// Expected subtitle:
// CHRISTMAS.
// SOMEONE THAT WOULD SIGN AWAY
// THEIR RIGHTS -- ELIZABETH HAS
for (j = 0; j < frame->side_data[i]->size/3; j+=3)
{
data = frame->side_data[i]->data[j];
if ((data & 0xF8) != 0xF8)
break;
cc_valid = data & 0x04;
cc_type = data & 3;
if (cc_type >= 2)
break;
if (cc_valid && cc_type == 0)
printf("cc field 1 %c%c\n",
CChar(frame->side_data[i]->data[j + 1]),
CChar(frame->side_data[i]->data[j + 2]));
else if (cc_valid && cc_type == 1)
printf("cc field 2 %c%c\n",
CChar(frame->side_data[i]->data[j + 1]),
CChar(frame->side_data[i]->data[j + 2]));
}
}
}
av_frame_unref(frame);
}
} while (ret == 0);
}
return decoded;
}
int main(int argc, char* argv[]) {
int ret = 0, got_frame;
AVFormatContext* fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, "Z:\\temp\\TestVid.ts", NULL, NULL);
avformat_find_stream_info(fmt_ctx, NULL);
video_stream_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_MPEG2VIDEO);
video_dec_ctx = avcodec_alloc_context3(codec);
if (avcodec_open2(video_dec_ctx, codec, NULL) < 0)
exit(1);
frame = av_frame_alloc();
av_init_packet(&pkt);
while (av_read_frame(fmt_ctx, &pkt) >= 0) {
do {
ret = decode_packet();
if (ret < 0)
break;
pkt.data += ret;
pkt.size -= ret;
} while (pkt.size > 0);
av_free_packet(&pkt);
}
getch();
}
More information about the Libav-user
mailing list