// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_gop_info(struct bitstream *esstream)
{
    dbg_print(DMT_VERBOSE, "Read GOP Info\n");

    // We only get here after seeing that start code
    if (next_u32(esstream) != 0xB8010000) // LSB first (0x000001B8)
        fatal(EXIT_BUG_BUG, "Impossible!");

    // If we get here esstream points to the start of a group_start_code
    // should we run out of data in esstream this is where we want to restart
    // after getting more.
    unsigned char *gop_info_start = esstream->pos;

    gop_header(esstream);
    //extension_and_user_data(esstream);

    if (esstream->error)
        return 0;

    if (esstream->bitsleft < 0)
    {
        init_bitstream(esstream, gop_info_start, esstream->end);
        return 0;
    }

    dbg_print(DMT_VERBOSE, "Read GOP Info - processed\n\n");

    return 1;
}
// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_seq_info(struct bitstream *esstream)
{
    dbg_print(DMT_VERBOSE, "Read Sequence Info\n");

    // We only get here after seeing that start code
    if (next_u32(esstream) != 0xB3010000) // LSB first (0x000001B3)
        fatal(EXIT_BUG_BUG, "read_seq_info: Impossible!");

    // If we get here esstream points to the start of a sequence_header_code
    // should we run out of data in esstream this is where we want to restart
    // after getting more.
    unsigned char *video_seq_start = esstream->pos;

    sequence_header(esstream);
    sequence_ext(esstream);
    // FIXME: if sequence extension is missing this is not MPEG-2,
    // or broken.  Set bitstream error.
    //extension_and_user_data(esstream);

    if (esstream->error)
        return 0;

    if (esstream->bitsleft < 0)
    {
        init_bitstream(esstream, video_seq_start, esstream->end);
        return 0;
    }

    dbg_print(DMT_VERBOSE, "Read Sequence Info - processed\n\n");

    return 1;
}
// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_gop_info(struct lib_cc_decode *ctx, struct bitstream *esstream, struct cc_subtitle *sub)
{
	debug("Read GOP Info\n");

	// We only get here after seeing that start code
	if (next_u32(esstream) != 0xB8010000) // LSB first (0x000001B8)
		fatal(CCX_COMMON_EXIT_BUG_BUG, "read_gop_info: next_u32(esstream) != 0xB8010000. Please file a bug report in GitHub.\n");

	// If we get here esstream points to the start of a group_start_code
	// should we run out of data in esstream this is where we want to restart
	// after getting more.
	unsigned char *gop_info_start = esstream->pos;

	gop_header(ctx, esstream, sub);
	//extension_and_user_data(esstream);

	if (esstream->error)
		return 0;

	if (esstream->bitsleft < 0)
	{
		init_bitstream(esstream, gop_info_start, esstream->end);
		return 0;
	}

	debug("Read GOP Info - processed\n\n");

	return 1;
}
// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_seq_info(struct lib_cc_decode *ctx, struct bitstream *esstream)
{
	debug("Read Sequence Info\n");

	// We only get here after seeing that start code
	if (next_u32(esstream) != 0xB3010000) // LSB first (0x000001B3)
		fatal(CCX_COMMON_EXIT_BUG_BUG, "read_seq_info: next_u32(esstream) != 0xB3010000. Please file a bug report in GitHub.\n");

	// If we get here esstream points to the start of a sequence_header_code
	// should we run out of data in esstream this is where we want to restart
	// after getting more.
	unsigned char *video_seq_start = esstream->pos;

	sequence_header(ctx, esstream);
	sequence_ext(ctx, esstream);
	// FIXME: if sequence extension is missing this is not MPEG-2,
	// or broken.  Set bitstream error.
	//extension_and_user_data(esstream);

	if (esstream->error)
		return 0;

	if (esstream->bitsleft < 0)
	{
		init_bitstream(esstream, video_seq_start, esstream->end);
		return 0;
	}

	debug("Read Sequence Info - processed\n\n");

	return 1;
}
// Return the next startcode or sequence_error_code if not enough
// data was left in the bitstream. Also set esstream->bitsleft.
// The bitstream pointer shall be moved to the begin of the start
// code if found, or to the position where a search would continue
// would more data be made available.
// Only NULL bytes before the start code are discarded, if a non
// NULL byte is encountered esstream->error is set to TRUE and the
// function returns sequence_error_code with the pointer set after
// that byte.
static uint8_t next_start_code(struct bitstream *esstream)
{
    if (esstream->error || esstream->bitsleft < 0)
    {
        return 0xB4;
    }

    make_byte_aligned(esstream);

    // Only start looking if there is enough data. Adjust bitsleft.
    if (esstream->bitsleft < 4*8)
    {
        dbg_print(DMT_VERBOSE, "next_start_code: bitsleft %lld < 32\n", esstream->bitsleft);
        esstream->bitsleft -= 8*4;
        return 0xB4;
    }

    uint8_t tmp;
    while ((next_u32(esstream)&0x00FFFFFF) != 0x00010000 // LSB 0x000001??
           && esstream->bitsleft > 0)
    {
        tmp = read_u8(esstream);
        if (tmp)
        {
            dbg_print(DMT_VERBOSE, "next_start_code: Non zero stuffing\n");
            esstream->error = 1;
            return 0xB4;
        }
    }

    if (esstream->bitsleft < 8)
    {
        esstream->bitsleft -= 8;
        dbg_print(DMT_VERBOSE, "next_start_code: bitsleft <= 0\n");
        return 0xB4;
    }
    else
    {
        dbg_print(DMT_VERBOSE, "next_start_code: Found %02X\n", *(esstream->pos+3));

        if ( *(esstream->pos+3) == 0xB4 )
        {
            dbg_print(DMT_VERBOSE, "B4: assume bitstream syntax error!\n");
            esstream->error = 1;
        }

        return *(esstream->pos+3);
    }
}
// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_pic_info(struct bitstream *esstream)
{
    dbg_print(DMT_VERBOSE, "Read PIC Info\n");

    // We only get here after seeing that start code
    if (next_u32(esstream) != 0x00010000) // LSB first (0x00000100)
        fatal(EXIT_BUG_BUG, "Impossible!");

    // If we get here esstream points to the start of a group_start_code
    // should we run out of data in esstream this is where we want to restart
    // after getting more.
    unsigned char *pic_info_start = esstream->pos;

    pic_header(esstream);
    pic_coding_ext(esstream);

    if (esstream->error)
        return 0;

    if (esstream->bitsleft < 0)
    {
        init_bitstream(esstream, pic_info_start, esstream->end);
        return 0;
    }

    // Analyse/use the picture information
    static int maxtref; // Use to remember the temporal reference number

    // A new anchor frame - flush buffered caption data. Might be flushed
    // in GOP header already.
    if (picture_coding_type==I_FRAME || picture_coding_type==P_FRAME)
    {		
//		if (((picture_structure != 0x1) && (picture_structure != 0x2)) ||
//		(temporal_reference != current_tref))
//		{
			// NOTE: process_hdcc() needs to be called before set_fts() as it
			// uses fts_now to re-create the timeline !!!!!
			if (has_ccdata_buffered)
			{
	            process_hdcc();
			}
			anchor_hdcc(temporal_reference);
//		}
    }

    current_tref = temporal_reference;
    current_picture_coding_type = picture_coding_type;

    // We mostly use PTS, but when the GOP mode is enabled do not set
    // the FTS time here.
    if (!use_gop_as_pts)
    {
        set_fts(); // Initialize fts
    }

    dbg_print(DMT_VIDES, "PTS: %s (%8u) - tref: %2d - %s  since tref0/GOP: %2u/%2u",
           print_mstime(current_pts/(MPEG_CLOCK_FREQ/1000)),
           unsigned(current_pts), temporal_reference,
       pict_types[picture_coding_type],
           unsigned(frames_since_ref_time),
           unsigned(frames_since_last_gop));
    dbg_print(DMT_VIDES, "  t:%d r:%d p:%d", top_field_first,
           repeat_first_field, progressive_frame);
    dbg_print(DMT_VIDES, "  FTS: %s\n", print_mstime(get_fts()));

    // Set min_pts/sync_pts according to the current time stamp.
    // Use fts_at_gop_start as reference when a GOP header was seen
    // since the last frame 0. If not this is most probably a
    // TS without GOP headers but with USER DATA after each picture
    // header. Use the current FTS values as reference.
    // Note: If a GOP header was present the reference time is from
    // the beginning of the GOP, otherwise it is now.
    if(temporal_reference == 0)
    {
        last_gop_length = maxtref + 1;
        maxtref = temporal_reference;

        // frames_since_ref_time is used in set_fts()

        if( saw_gop_header )
        {
            // This time (fts_at_gop_start) that was set in the
            // GOP header and it might be off by one GOP. See the comment there.
            frames_since_ref_time = frames_since_last_gop; // Should this be 0?
        }
        else
        {
            // No GOP header, use the current values
            fts_at_gop_start=get_fts();
            frames_since_ref_time = 0;
        }

        if (debug_mask & DMT_TIME)
        {
            dbg_print(DMT_TIME, "\nNew temporal reference:\n");
            print_debug_timing();
        }

        saw_gop_header = 0; // Reset the value
    }

    if ( !saw_gop_header && picture_coding_type==I_FRAME )
    {
        // A new GOP beginns with an I-frame. Lets hope there are
        // never more than one per GOP
        frames_since_last_gop = 0;
    }

    // Set maxtref
    if( temporal_reference > maxtref ) {
        maxtref = temporal_reference;
        if (maxtref+1 > max_gop_length)
            max_gop_length = maxtref+1;
    }

    unsigned extraframe = 0;
    if (repeat_first_field)
    {
        pulldownfields++;
        total_pulldownfields++;
        if ( current_progressive_sequence || !(total_pulldownfields%2) )
            extraframe = 1;
        if ( current_progressive_sequence && top_field_first )
            extraframe = 2;
        dbg_print(DMT_VIDES, "Pulldown: total pd fields: %d - %d extra frames\n",
                   total_pulldownfields, extraframe);
    }

    total_pulldownframes += extraframe;
    total_frames_count += 1+extraframe;
    frames_since_last_gop += 1+extraframe;
    frames_since_ref_time += 1+extraframe;

    dbg_print(DMT_VERBOSE, "Read PIC Info - processed\n\n");

    return 1;
}
// Return TRUE if all was read.  FALSE if a problem occured:
// If a bitstream syntax problem occured the bitstream will
// point to after the problem, in case we run out of data the bitstream
// will point to where we want to restart after getting more.
static int read_pic_info(struct lib_cc_decode *ctx, struct bitstream *esstream, struct cc_subtitle *sub)
{
	debug("Read PIC Info\n");

	// We only get here after seeing that start code
	if (next_u32(esstream) != 0x00010000) // LSB first (0x00000100)
		fatal(CCX_COMMON_EXIT_BUG_BUG, "In read_pic_info: next_u32(esstream) != 0x00010000. Please file a bug report in GitHub.\n");

	// If we get here esstream points to the start of a group_start_code
	// should we run out of data in esstream this is where we want to restart
	// after getting more.
	unsigned char *pic_info_start = esstream->pos;

	pic_header(ctx, esstream);
	pic_coding_ext(ctx, esstream);

	if (esstream->error)
		return 0;

	if (esstream->bitsleft < 0)
	{
		init_bitstream(esstream, pic_info_start, esstream->end);
		return 0;
	}

	// A new anchor frame - flush buffered caption data. Might be flushed
	// in GOP header already.
	if (ctx->picture_coding_type==CCX_FRAME_TYPE_I_FRAME || ctx->picture_coding_type==CCX_FRAME_TYPE_P_FRAME)
	{
		if (((ctx->picture_structure != 0x1) && (ctx->picture_structure != 0x2)) ||
				(ctx->temporal_reference != ctx->timing->current_tref))
		{
			// NOTE: process_hdcc() needs to be called before set_fts() as it
			// uses fts_now to re-create the timeline !!!!!
			if (ctx->has_ccdata_buffered)
			{
				process_hdcc(ctx, sub);
			}
			anchor_hdcc(ctx, ctx->temporal_reference);
		}
	}

	ctx->timing->current_tref = ctx->temporal_reference;
	ctx->timing->current_picture_coding_type = ctx->picture_coding_type;

	// We mostly use PTS, but when the GOP mode is enabled do not set
	// the FTS time here.
	if (ccx_options.use_gop_as_pts!=1)
	{
		set_fts(ctx->timing); // Initialize fts
	}

	dbg_print(CCX_DMT_VIDES, "  t:%d r:%d p:%d", ctx->top_field_first,
			ctx->repeat_first_field, ctx->progressive_frame);
	dbg_print(CCX_DMT_VIDES, "  FTS: %s\n", print_mstime_static(get_fts(ctx->timing, ctx->current_field)));

	// Set min_pts/sync_pts according to the current time stamp.
	// Use fts_at_gop_start as reference when a GOP header was seen
	// since the last frame 0. If not this is most probably a
	// TS without GOP headers but with USER DATA after each picture
	// header. Use the current FTS values as reference.
	// Note: If a GOP header was present the reference time is from
	// the beginning of the GOP, otherwise it is now.
	if(ctx->temporal_reference == 0)
	{
		ctx->last_gop_length = ctx->maxtref + 1;
		ctx->maxtref = ctx->temporal_reference;

		// frames_since_ref_time is used in set_fts()

		if( ctx->saw_gop_header )
		{
			// This time (fts_at_gop_start) that was set in the
			// GOP header and it might be off by one GOP. See the comment there.
			frames_since_ref_time = ctx->frames_since_last_gop; // Should this be 0?
		}
		else
		{
			// No GOP header, use the current values
			fts_at_gop_start = get_fts(ctx->timing, ctx->current_field);
			frames_since_ref_time = 0;
		}

		if (ccx_options.debug_mask & CCX_DMT_TIME)
		{
			dbg_print(CCX_DMT_TIME, "\nNew temporal reference:\n");
			print_debug_timing(ctx->timing);
		}

		ctx->saw_gop_header = 0; // Reset the value
	}

	if ( !ctx->saw_gop_header && ctx->picture_coding_type==CCX_FRAME_TYPE_I_FRAME )
	{
		// A new GOP beginns with an I-frame. Lets hope there are
		// never more than one per GOP
		ctx->frames_since_last_gop = 0;
	}

	// Set maxtref
	if( ctx->temporal_reference > ctx->maxtref ) {
		ctx->maxtref = ctx->temporal_reference;
		if (ctx->maxtref + 1 > ctx->max_gop_length)
			ctx->max_gop_length = ctx->maxtref + 1;
	}

	unsigned extraframe = 0;
	if (ctx->repeat_first_field)
	{
		ctx->pulldownfields++;
		ctx->total_pulldownfields++;
		if ( ctx->current_progressive_sequence || !(ctx->total_pulldownfields%2) )
			extraframe = 1;
		if ( ctx->current_progressive_sequence && ctx->top_field_first )
			extraframe = 2;
		dbg_print(CCX_DMT_VIDES, "Pulldown: total pd fields: %d - %d extra frames\n",
				ctx->total_pulldownfields, extraframe);
	}

	ctx->total_pulldownframes += extraframe;
	total_frames_count += 1+extraframe;
	ctx->frames_since_last_gop += 1+extraframe;
	frames_since_ref_time += 1+extraframe;

	debug("Read PIC Info - processed\n\n");

	return 1;
}