Split out Philips code parsing into a separate utility module.

Rewrote Philips code parsing to be clock based.
Updated makemeta to call the new function.
This commit is contained in:
Aaron Giles 2008-07-08 07:55:49 +00:00
parent bdbc3226c6
commit d256dc7e88
5 changed files with 169 additions and 99 deletions

2
.gitattributes vendored
View File

@ -1023,6 +1023,8 @@ src/lib/util/unicode.c svneol=native#text/plain
src/lib/util/unicode.h svneol=native#text/plain
src/lib/util/unzip.c svneol=native#text/plain
src/lib/util/unzip.h svneol=native#text/plain
src/lib/util/vbiparse.c svneol=native#text/plain
src/lib/util/vbiparse.h svneol=native#text/plain
src/lib/util/xmlfile.c svneol=native#text/plain
src/lib/util/xmlfile.h svneol=native#text/plain
src/lib/zlib/Makefile svneol=native#text/plain

View File

@ -44,6 +44,7 @@ UTILOBJS = \
$(LIBOBJ)/util/sha1.o \
$(LIBOBJ)/util/unicode.o \
$(LIBOBJ)/util/unzip.o \
$(LIBOBJ)/util/vbiparse.o \
$(LIBOBJ)/util/xmlfile.o \
$(OBJ)/libutil.a: $(UTILOBJS)

137
src/lib/util/vbiparse.c Normal file
View File

@ -0,0 +1,137 @@
/***************************************************************************
vbiparse.c
Parse Philips codes and other data from VBI lines.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include "aviio.h"
#include "bitmap.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
#define MAX_SOURCE_WIDTH 1024
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
vbi_parse_line - parse a Philips code from a
line of video data
-------------------------------------------------*/
int vbi_parse_line(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT8 *result)
{
UINT8 srcabs[MAX_SOURCE_WIDTH];
UINT8 min, max, mid, srcabsval;
double clock, bestclock;
int x, firstedge;
int besterr;
/* find highs and lows in the line */
min = 0xff;
max = 0x00;
for (x = 0; x < sourcewidth; x++)
{
UINT8 rawsrc = source[x] >> sourceshift;
min = MIN(min, rawsrc);
max = MAX(max, rawsrc);
}
/* bail if the line is all black or all white */
if (max < 0x80 || min > 0x80)
return 0;
/* determine the midpoint and then set the thresholds to be halfway */
mid = (min + max) / 2;
min = mid - (mid - min) / 2;
max = mid + (max - mid) / 2;
/* convert the source into absolute high/low */
srcabsval = (source[0] > mid);
for (x = 0; x < sourcewidth; x++)
{
UINT8 rawsrc = source[x] >> sourceshift;
if (rawsrc >= max)
srcabsval = 1;
else if (rawsrc <= min)
srcabsval = 0;
srcabs[x] = srcabsval;
}
/* find the first transition; this is assumed to be the middle of the first bit */
for (x = 0; x < sourcewidth - 1; x++)
if (srcabs[x] != srcabs[x + 1])
break;
if (x == sourcewidth - 1)
return 0;
firstedge = x;
/* now scan to find a clock that has a nearby transition on each beat */
bestclock = 0;
besterr = 1000;
for (clock = (double)sourcewidth / (double)expectedbits; clock >= 2.0; clock -= 1.0 / (double)expectedbits)
{
int error = 0;
/* scan for all the expected bits */
for (x = 1; x < expectedbits; x++)
{
int curbit = firstedge + (double)x * clock;
/* exact match? */
if (srcabs[curbit + 0] != srcabs[curbit + 1])
continue;
/* off-by-one? */
if (srcabs[curbit + 1 + 0] != srcabs[curbit + 1 + 1] || srcabs[curbit - 1 + 0] != srcabs[curbit - 1 + 1])
{
/* only continue if we're still in the running */
if (++error < besterr)
continue;
}
/* anything else fails immediately */
break;
}
/* if we got to the end, this is the best candidate so far */
if (x == expectedbits)
{
besterr = error;
bestclock = clock;
}
}
/* if nobody matched, fail */
if (bestclock == 0)
return 0;
/* now extract the bits */
for (x = 0; x < expectedbits; x++)
{
int leftbit = firstedge + ((double)x - 0.25) * bestclock;
int rightbit = firstedge + ((double)x + 0.25) * bestclock;
int left = srcabs[leftbit];
int right = srcabs[rightbit];
/* all bits should be marked by transitions; fail if we don't get one */
if (left == right)
return 0;
result[x] = (left < right);
}
return expectedbits;
}

25
src/lib/util/vbiparse.h Normal file
View File

@ -0,0 +1,25 @@
/***************************************************************************
vbiparse.h
Parse Philips codes and other data from VBI lines.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#pragma once
#ifndef __VBIPARSE_H__
#define __VBIPARSE_H__
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* parse a Philips code from a line of video data */
int vbi_parse_line(const UINT16 *source, int sourcewidth, int sourceshift, int expectedbits, UINT8 *result);
#endif /* __VBIPARSE_H__ */

View File

@ -28,6 +28,7 @@
#include <ctype.h>
#include "aviio.h"
#include "bitmap.h"
#include "vbiparse.h"
@ -59,85 +60,6 @@ struct _pattern_data
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
parse_line - parse a Philips code from a
line of video data
-------------------------------------------------*/
static int parse_line(bitmap_t *bitmap, int line, int expected_bits, UINT8 *result)
{
const UINT16 *source = BITMAP_ADDR16(bitmap, line, 0);
int x, edges = 0, bits = 0;
int minwidth = 1000;
UINT8 bit[720];
int edge[720];
int error = 0;
/* clamp expected bits */
expected_bits *= 2;
if (expected_bits > ARRAY_LENGTH(edge) - 1)
expected_bits = ARRAY_LENGTH(edge) - 1;
/* find the edges in the line */
for (x = 1; x < bitmap->width && edges < ARRAY_LENGTH(edge); x++)
if (source[x] >= 0xc000 && source[x - 1] < 0xc000)
edge[edges++] = x;
else if (source[x] <= 0x4000 && source[x - 1] > 0x4000)
edge[edges++] = x;
/* find the minimum width */
for (x = 1; x < edges; x++)
{
int width = edge[x] - edge[x - 1];
if (width > 3 && width < minwidth)
minwidth = edge[x] - edge[x - 1];
}
/* now generate the bits */
for (x = 1; x < edges; x++)
{
int width = edge[x] - edge[x - 1];
if (width > 3)
{
int count = (width > 3 * minwidth / 2) ? 2 : 1;
while (count--)
bit[bits++] = (source[edge[x - 1]] >= 0x8000) ? 1 : 0;
}
}
/* look for improperly paired bits in the sequence */
if (bits < expected_bits)
{
/* look for two bits in a row of the same type on an even boundary */
for (x = 0; x < bits; x += 2)
if (bit[x] == bit[x + 1])
break;
/* if we got something wrong, assume we're missing an opening 0 bit */
if (x < bits)
{
memmove(&bit[1], &bit[0], bits);
bit[0] = 0;
bits++;
}
}
/* trailing bits are 0 */
while (bits < expected_bits)
bit[bits++] = 0;
/* output */
for (x = 0; x < MIN(bits, expected_bits); x += 2)
{
static const UINT8 trans[4] = { 0x80, 1, 0, 0xff };
result[x/2] = trans[(bit[x] << 1) | bit[x + 1]];
if (result[x/2] > 1)
error++;
}
return error ? -(bits / 2) : (bits / 2);
}
/*-------------------------------------------------
output_meta - output a line of metadata
-------------------------------------------------*/
@ -227,23 +149,6 @@ static int generate_from_avi(const char *aviname)
int prevwhite = white;
int i;
{
static FILE *f;
int line;
if (!f) f = fopen("temp.log", "w");
fprintf(f, "\n\nFrame %d, field %d\n", frame, field);
for (line = 0; line < 22; line++)
{
UINT16 *src = BITMAP_ADDR16(bitmap, line*2 + field, 0);
int x;
for (x = 0; x < bitmap->width; x++)
fprintf(f, "%04X ", *src++);
fprintf(f, "\n");
}
fflush(f);
}
/* line 11 contains the white flag */
white = 0;
if (*BITMAP_ADDR16(bitmap, 11*2 + field, bitmap->width / 2) > 0x8000)
@ -261,18 +166,18 @@ static int generate_from_avi(const char *aviname)
/* line 16 contains stop code and other interesting bits */
line16 = 0;
if (parse_line(bitmap, 16*2 + field, 24, bits) == 24)
if (vbi_parse_line(BITMAP_ADDR16(bitmap, 16*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
for (i = 0; i < 24; i++)
line16 = (line16 << 1) | bits[i];
/* line 17 and 18 contain frame/chapter/lead in/out encodings */
line17 = 0;
if (parse_line(bitmap, 17*2 + field, 24, bits) == 24)
if (vbi_parse_line(BITMAP_ADDR16(bitmap, 17*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
for (i = 0; i < 24; i++)
line17 = (line17 << 1) | bits[i];
line18 = 0;
if (parse_line(bitmap, 18*2 + field, 24, bits) == 24)
if (vbi_parse_line(BITMAP_ADDR16(bitmap, 18*2 + field, 0), bitmap->width, 8, 24, bits) == 24)
for (i = 0; i < 24; i++)
line18 = (line18 << 1) | bits[i];