Esempio n. 1
0
/* Helper function for to display debug timing info. */
void print_debug_timing( void )
{
    // Avoid wrong "Calc. difference" and "Asynchronous by" numbers
    // for uninitialized min_pts
    LLONG tempmin_pts = (min_pts==0x01FFFFFFFFLL ? sync_pts : min_pts);

    mprint("Sync time stamps:  PTS: %s                ",
           print_mstime((sync_pts)/(MPEG_CLOCK_FREQ/1000)) );
    mprint("GOP: %s      \n", print_mstime(gop_time.ms));

    // Length first GOP to last GOP
    LLONG goplenms = LLONG(gop_time.ms - first_gop_time.ms);
    // Length at last sync point
    LLONG ptslenms = unsigned((sync_pts-tempmin_pts)/(MPEG_CLOCK_FREQ/1000)
                              + fts_offset);

    mprint("Last               FTS: %s",
           print_mstime(get_fts_max()));
    mprint("      GOP start FTS: %s\n",
           print_mstime(fts_at_gop_start));

    // Times are based on last GOP and/or sync time
    mprint("Max FTS diff. to   PTS:       %6lldms              GOP:       %6lldms\n\n",
           get_fts_max()+LLONG(1000.0/current_fps)-ptslenms,
           get_fts_max()+LLONG(1000.0/current_fps)-goplenms);
}
Esempio n. 2
0
void calculate_ms_gop_time (struct gop_time_code *g)
{
    int seconds=(g->time_code_hours*3600)+(g->time_code_minutes*60)+g->time_code_seconds;
    g->ms = LLONG( 1000*(seconds + g->time_code_pictures/current_fps) );
    if (gop_rollover)
        g->ms += 24*60*60*1000;
}
Esempio n. 3
0
// Buffer caption blocks for later sorting/flushing.
void store_hdcc(unsigned char *cc_data, int cc_count, int sequence_number, LLONG current_fts_now)
{
    // Uninitialized?
    if (anchor_seq_number < 0)
    {
        anchor_hdcc( sequence_number);
    }

    int seq_index = sequence_number - anchor_seq_number + MAXBFRAMES;

    if (seq_index < 0 || seq_index > 2*MAXBFRAMES)
    {
        // Maybe missing an anchor frame - try to recover
        dbg_print(DMT_VERBOSE, "Too many B-frames, or missing anchor frame. Trying to recover ..\n");

        process_hdcc();
        anchor_hdcc( sequence_number);
        seq_index = sequence_number - anchor_seq_number + MAXBFRAMES;
    }

    has_ccdata_buffered = 1;

	// In GOP mode the fts is set only once for the whole GOP. Recreate
    // the right time according to the sequence number.
    if (use_gop_as_pts==1)
    {
        current_fts_now += LLONG(sequence_number*1000.0/current_fps);
    }

	if (cc_count)
	{		
		if (cc_data)
		{		
			// Changed by CFS to concat, i.e. don't assume there's no data already for this seq_index.
			// Needed at least for MP4 samples. // TODO: make sure we don't overflow
			cc_fts[seq_index] = current_fts_now; // CFS: Maybe do even if there's no data?
			if (stream_mode!=SM_MP4) // CFS: Very ugly hack, but looks like overwriting is needed for at least some ES
				cc_data_count[seq_index]  = 0;
			memcpy(cc_data_pkts[seq_index]+cc_data_count[seq_index]*3, cc_data, cc_count*3+1);
		}
		cc_data_count[seq_index] += cc_count;
	}
    // DEBUG STUFF
/*
    printf("\nCC blocks, channel 0:\n");
    for ( int i=0; i < cc_count*3; i+=3)
    {
        printf("%s", debug_608toASC( cc_data+i, 0) );
    }
    printf("\n");
*/
}
Esempio n. 4
0
// Buffer caption blocks for later sorting/flushing.
void store_hdcc(unsigned char *cc_data, int cc_count, int sequence_number, LLONG current_fts_now)
{
    // Uninitialized?
    if (anchor_seq_number < 0)
    {
        anchor_hdcc( sequence_number);
    }

    int seq_index = sequence_number - anchor_seq_number + MAXBFRAMES;

    if (seq_index < 0 || seq_index > 2*MAXBFRAMES)
    {
        // Maybe missing an anchor frame - try to recover
        if(debug_verbose)
            printf("Too many B-frames, or missing anchor frame. Trying to recover ..\n");

        process_hdcc();
        anchor_hdcc( sequence_number);
        seq_index = sequence_number - anchor_seq_number + MAXBFRAMES;
    }

    has_ccdata_buffered = 1;
    cc_data_count[seq_index] = cc_count;

    // In GOP mode the fts is set only once for the whole GOP. Recreate
    // the right time according to the sequence number.
    if (use_gop_as_pts)
    {
        current_fts_now += LLONG(sequence_number*1000.0/current_fps);
    }
    cc_fts[seq_index] = current_fts_now;
    memcpy(cc_data_pkts[seq_index], cc_data, cc_count*3+1);

    // DEBUG STUFF
/*
    printf("\nCC blocks, channel 0:\n");
    for ( int i=0; i < cc_count*3; i+=3)
    {
        printf("%s", debug_608toASC( cc_data+i, 0) );
    }
    printf("\n");
*/
}
Esempio n. 5
0
void set_fts(void)
{
    int pts_jump = 0;

    // ES don't have PTS unless GOP timing is used
    if (!pts_set && stream_mode==SM_ELEMENTARY_OR_NOT_FOUND)
        return;

    // First check for timeline jump (only when min_pts was
    // set (implies sync_pts).
    int dif = 0;
    if (pts_set == 2)
    {
        dif=(int) (current_pts-sync_pts)/MPEG_CLOCK_FREQ;

        // Used to distinguish gaps with missing caption information from
        // jumps in the timeline.  (Currently only used for dvr-ms/NTSC
        // recordings)
        if ( CaptionGap )
            dif = 0;

        // Disable sync check for raw formats - they have the right timeline.
        // Also true for bin formats, but -nosync might have created a
        // broken timeline for debug purposes.
		// Disable too in MP4, specs doesn't say that there can't be a jump
        switch (stream_mode)
        {
            case SM_MCPOODLESRAW:
            case SM_RCWT:
			case SM_MP4:
                dif = 0;
                break;
            default:
                break;
        }

        if (dif < -0.2 || dif >=5 )
        {
            // ATSC specs: More than 3501 ms means missing component
            mprint ("\nWarning: Reference clock has changed abruptly (%d seconds), attempting to synchronize\n", (int) dif);
            mprint ("Last sync PTS value: %lld\n",sync_pts);
            mprint ("Current PTS value: %lld\n",current_pts);
            pts_jump = 1;
            pts_big_change=1;

            // Discard the gap if it is not on an I-frame or temporal reference
            // zero.
            if(current_tref != 0 && current_picture_coding_type != I_FRAME)
            {
                fts_now = fts_max;
                mprint ("Change did not occur on first frame - probably a broken GOP\n");
                return;
            }
        }
    }

    // Set min_pts, fts_offset
    if (pts_set!=0)
    {
        pts_set=2;

        // Use this part only the first time min_pts is set. Later treat
        // it as a reference clock change
        if (current_pts<min_pts && !pts_jump)
        {
            // If this is the first GOP, and seq 0 was not encountered yet
            // we might reset min_pts/fts_offset again

            min_pts=current_pts;

            // Avoid next async test
            sync_pts = LLONG(current_pts
                             -current_tref*1000.0/current_fps
                             *(MPEG_CLOCK_FREQ/1000));

            if(current_tref == 0)
            {   // Earliest time in GOP.
                fts_offset = 0;
            }
            else if ( total_frames_count-frames_since_ref_time == 0 )
            {   // If this is the first frame (PES) there cannot be an offset.
                // This part is also reached for dvr-ms/NTSC (RAW) as 
                // total_frames_count = frames_since_ref_time = 0 when
                // this is called for the first time.
                fts_offset = 0;
            }
            else
            {   // It needs to be "+1" because the current frame is
                // not yet counted.
                fts_offset = LLONG((total_frames_count
                                    -frames_since_ref_time+1)
                                   *1000.0/current_fps);
            }
            dbg_print(DMT_TIME, "\nFirst sync time    PTS: %s %+lldms (time before this PTS)\n",
                   print_mstime(min_pts/(MPEG_CLOCK_FREQ/1000)),
                   fts_offset );
            dbg_print(DMT_TIME, "Total_frames_count %u frames_since_ref_time %u\n",
                   total_frames_count, frames_since_ref_time);
        }

        // -nosync diasbles syncing
        if (pts_jump && !nosync)
        {
            // The current time in the old time base is calculated using
            // sync_pts (set at the beginning of the last GOP) plus the
            // time of the frames since then.
            fts_offset = fts_offset
                + (sync_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
                + LLONG(frames_since_ref_time*1000/current_fps);
            fts_max = fts_offset;

            // Start counting again from here
            pts_set=1; // Force min to be set again

            // Avoid next async test - the gap might have occured on
            // current_tref != 0.
            sync_pts = LLONG(current_pts
                             -current_tref*1000.0/current_fps
                             *(MPEG_CLOCK_FREQ/1000));
            // Set min_pts = sync_pts as this is used for fts_now
            min_pts = sync_pts;

            dbg_print(DMT_TIME, "\nNew min PTS time: %s %+lldms (time before this PTS)\n",
                   print_mstime(min_pts/(MPEG_CLOCK_FREQ/1000)),
                   fts_offset );
        }
    }

    // Set sync_pts, fts_offset
    if(current_tref == 0)
        sync_pts = current_pts;

    // Reset counters
    cb_field1 = 0;
    cb_field2 = 0;
    cb_708 = 0;

    // Avoid wrong "Calc. difference" and "Asynchronous by" numbers
    // for uninitialized min_pts
	if (1) // CFS: Remove or think decent condition
	{
		if ( pts_set )
		{
			// If pts_set is TRUE we have min_pts
			fts_now = LLONG((current_pts-min_pts)/(MPEG_CLOCK_FREQ/1000)
							+ fts_offset);
		}
		else
		{
			// No PTS info at all!!
			fatal(EXIT_BUG_BUG,
				  "No PTS info. Please write bug report.");
		}
	}
    if ( fts_now > fts_max )
    {
        fts_max = fts_now;
    }
}
Esempio n. 6
0
// Return TRUE if the data parsing finished, FALSE otherwise.
// estream->pos is advanced. Data is only processed if esstream->error
// is FALSE, parsing can set esstream->error to TRUE.
static int gop_header(struct bitstream *esstream)
{
    dbg_print(DMT_VERBOSE, "GOP header\n");

    if (esstream->error || esstream->bitsleft <= 0)
        return 0;

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

    unsigned drop_frame_flag = (unsigned) read_bits(esstream,1);
    struct gop_time_code gtc;
    gtc.time_code_hours = (int) read_bits(esstream,5);
    gtc.time_code_minutes = (int) read_bits(esstream,6);
    skip_bits(esstream,1); // Marker bit
    gtc.time_code_seconds = (int) read_bits(esstream,6);
    gtc.time_code_pictures = (int) read_bits(esstream,6);
    gtc.inited = 1;
    calculate_ms_gop_time(&gtc);

    if (esstream->bitsleft < 0)
        return 0;

    if (gop_accepted(&gtc))
    {
        // Do GOP padding during GOP header. The previous GOP and all
        // included captions are written. Use the current GOP time to
        // do the padding.

        // Flush buffered cc blocks before doing the housekeeping
        if (has_ccdata_buffered)
        {
            process_hdcc();
        }

        // Last GOPs pulldown frames
        if ((current_pulldownfields>0) != (pulldownfields>0))
        {
            current_pulldownfields = pulldownfields;
            dbg_print(DMT_VERBOSE, "Pulldown: %s", (pulldownfields ? "on" : "off"));
            if (pulldownfields)
                dbg_print(DMT_VERBOSE, " - %u fields in last GOP", pulldownfields);
            dbg_print(DMT_VERBOSE, "\n");
        }
        pulldownfields = 0;

        // Report synchronization jumps between GOPs. Warn if there
        // are 20% or more deviation.
        if ( (debug_mask & DMT_TIME)
             && ((gtc.ms - gop_time.ms // more than 20% longer
                  > frames_since_last_gop*1000.0/current_fps*1.2)
                 ||
                 (gtc.ms - gop_time.ms // or 20% shorter
                  < frames_since_last_gop*1000.0/current_fps*0.8))
             && first_gop_time.inited )
        {
            mprint("\rWarning: Jump in GOP timing.\n");
            mprint("  (old) %s",
                   print_mstime(gop_time.ms));
            mprint("  +  %s (%uF)",
                   print_mstime(LLONG(frames_since_last_gop
                                      *1000.0/current_fps)),
                   frames_since_last_gop);
            mprint("  !=  (new) %s\n",
                   print_mstime(gtc.ms));
        }

        if (first_gop_time.inited == 0)
        {
            first_gop_time = gtc;

            // It needs to be "+1" because the frame count starts at 0 and we
            // need the length of all frames.
            if ( total_frames_count == 0 )
            {   // If this is the first frame there cannot be an offset
                fts_fc_offset = 0;
                // first_gop_time.ms stays unchanged
            }
            else
            {
                fts_fc_offset = LLONG((total_frames_count+1)
                                      *1000.0/current_fps);
                // Compensate for those written before
                first_gop_time.ms -= fts_fc_offset;
            }

            dbg_print(DMT_TIME, "\nFirst GOP time: %02u:%02u:%02u:%03u %+lldms\n",
                    gtc.time_code_hours,
                    gtc.time_code_minutes, gtc.time_code_seconds,
                    unsigned(1000.0*gtc.time_code_pictures/current_fps),
                    fts_fc_offset);
        }

        gop_time = gtc;

        frames_since_last_gop=0;
        // Indicate that we read a gop header (since last frame number 0)
        saw_gop_header = 1;

        // If we use GOP timing, reconstruct the PTS from the GOP
        if (use_gop_as_pts)
        {
            current_pts = gtc.ms*(MPEG_CLOCK_FREQ/1000);
            if (pts_set==0)
                pts_set=1;
            current_tref = 0;
            frames_since_ref_time = 0;
            set_fts();
            fts_at_gop_start = get_fts_max();
        }
        else
        {
            // FIXME: Wrong when PTS are not increasing but are identical
            // troughout the GOP and then jump to the next time for the
            // next GOP.
            // This effect will also lead to captions being one GOP early
            // for DVD captions.
            fts_at_gop_start = get_fts_max() + LLONG(1000.0/current_fps);
        }

        if (debug_mask & DMT_TIME)
        {
            dbg_print(DMT_TIME, "\nNew GOP:\n");
            dbg_print(DMT_TIME, "\nDrop frame flag: %u:\n", drop_frame_flag);
            print_debug_timing();
        }
    }

    return 1;
}