ldverify now prints transient progress to stderr, allows for frame #0,

and reports if no white flags were seen.

Fixed bug in aviio.c which could cause an infinite loop if attempting
to read sound beyond the end of the file.

Rewrote the white flag detection to use a histogram for outlier detection
and peak identification.
This commit is contained in:
Aaron Giles 2008-08-07 15:07:12 +00:00
parent 1c6a1e7df7
commit 3107dc2dff
3 changed files with 110 additions and 16 deletions

View File

@ -863,6 +863,13 @@ avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample
chunkbase = chunkend;
}
/* if we hit the end, fill the rest with silence */
if (chunknum == stream->chunks)
{
memset(output, 0, numsamples * 2);
break;
}
/* expand the tempbuffer to hold the data if necessary */
avierr = expand_tempbuffer(file, stream->chunk[chunknum].length);
if (avierr != AVIERR_NONE)

View File

@ -15,6 +15,14 @@
/***************************************************************************
DEBUGGING
***************************************************************************/
#define PRINTF_WHITE_FLAG 0
/***************************************************************************
CONSTANTS
***************************************************************************/
@ -169,25 +177,98 @@ int vbi_parse_manchester_code(const UINT16 *source, int sourcewidth, int sources
int vbi_parse_white_flag(const UINT16 *source, int sourcewidth, int sourceshift)
{
int histo[256] = { 0 };
int minval = 0xff;
int maxval = 0x00;
int avgval = 0x00;
int diff;
int subtract;
int peakval;
int result;
int x;
/* compute minimum, maximum, and average values across the line */
/* compute a histogram of values */
for (x = 0; x < sourcewidth; x++)
{
UINT8 yval = source[x] >> sourceshift;
minval = MIN(yval, minval);
maxval = MAX(yval, maxval);
avgval += yval;
histo[yval]++;
}
avgval /= sourcewidth;
diff = maxval - minval;
/* remove the lowest 1% of the values to account for noise and determine the minimum */
subtract = sourcewidth / 100;
for (minval = 0; minval < 255; minval++)
if ((subtract -= histo[minval]) < 0)
break;
/* if there's a spread of at least 0x20, and the average is above 3/4 of the center, call it good */
return (diff >= 0x20) && (avgval >= minval + 3 * diff / 4);
/* remove the highest 1% of the values to account for noise and determine the maximum */
subtract = sourcewidth / 100;
for (maxval = 255; maxval > 0; maxval--)
if ((subtract -= histo[maxval]) < 0)
break;
/* this is useful for debugging issues with white flag detection */
if (PRINTF_WHITE_FLAG)
{
printf("Histo: min=%02X max=%02X\n", minval, maxval);
for (x = 0; x < 256; x++)
if (histo[x] != 0) printf("%dx%02X\n", histo[x], x);
}
/* ignore if we have no dynamic range */
if (maxval - minval < 10)
{
if (PRINTF_WHITE_FLAG)
printf("White flag NOT detected; threshold too low\n");
return FALSE;
}
/*
At this point, there are two approaches that have been tried:
1. Find the peak value and call it white if the peak is above
the 90% line
2. Ignore the first and last 20% of the line and count how
many pixels are above some threshold (75% line was used).
Call it white if at least 80% of the pixels are above
the threshold.
Both approaches agree 99% of the time, but the first tends to
be more correct when there is a discrepancy.
*/
/* determine where the peak is */
peakval = 0;
for (x = 1; x < 256; x++)
if (histo[x] > histo[peakval])
peakval = x;
/* return TRUE if it is above the 90% mark */
result = (peakval > minval + 9 * (maxval - minval) / 10);
if (PRINTF_WHITE_FLAG)
printf("White flag %s: peak=%02X thresh=%02X\n", result ? "detected" : "NOT detected", peakval, minval + 9 * (maxval - minval) / 10);
return result;
#ifdef UNUSED_CODE
{
int above = 0;
int thresh;
/* alternate approach: */
/* ignore the first 1/5 and last 1/5 of the line for the remaining computations */
source += sourcewidth / 5;
sourcewidth -= 2 * (sourcewidth / 5);
/* count how many values were above the 75% mark of the range */
thresh = minval + 3 * (maxval - minval) / 4;
for (x = 0; x < sourcewidth; x++)
{
UINT8 yval = source[x] >> sourceshift;
above += (yval >= thresh);
}
/* if at least 80% of the pixels are above the threshold, we'll call it white */
return ((above * 100) / sourcewidth >= 80);
}
#endif
}

View File

@ -310,7 +310,7 @@ static void verify_video(int frame, bitmap_t *bitmap)
/* output status */
if (frame % 10 == 0 && fieldnum == 0)
printf("%6d.%d...\r", frame, fieldnum);
fprintf(stderr, "%6d.%d...\r", frame, fieldnum);
/* parse the VBI data */
vbi_parse_all(BITMAP_ADDR16(bitmap, fieldnum, 0), bitmap->rowpixels * 2, bitmap->width, 8, &metadata);
@ -371,14 +371,16 @@ static void verify_video(int frame, bitmap_t *bitmap)
/* if this is the first frame, make sure it's 1 */
if (video_last_frame == -1)
{
if (framenum == 1)
if (framenum == 0)
printf("%6d.%d: detected frame 0\n", frame, fieldnum);
else if (framenum == 1)
printf("%6d.%d: detected frame 1\n", frame, fieldnum);
else
printf("%6d.%d: first frame number is not 1 (%d) (ERROR)\n", frame, fieldnum, framenum);
printf("%6d.%d: first frame number is not 0 or 1 (%d) (ERROR)\n", frame, fieldnum, framenum);
}
/* print an update every 1000 frames */
if (framenum % 1000 == 0)
/* print an update every 10000 frames */
if (framenum != 0 && framenum % 10000 == 0)
printf("%6d.%d: detected frame %d\n", frame, fieldnum, framenum);
/* if this frame is not consecutive, it's an error */
@ -464,6 +466,10 @@ static void verify_video_final(int frame, bitmap_t *bitmap)
{
int fields_per_frame = (bitmap->height >= 288) ? 2 : 1;
int field = frame * fields_per_frame;
/* did we ever see any white flags? */
if (video_first_whitefield == -1)
printf("Track %6d.%d: never saw any white flags; no cadence detection done (WARNING)\n", field / fields_per_frame, 0);
/* did we ever see any lead-out? */
if (video_saw_leadin && !video_saw_leadout)