hdvparse: Emit application message with the parsed information.

This commit is contained in:
Edward Hervey 2009-05-31 18:23:08 +02:00
parent c6cd4d09e2
commit 5df5059d56

View file

@ -55,6 +55,90 @@ enum
PROP_0,
};
static gchar *aperture_table[] = {
"???",
"cls",
"1.0",
"1.2",
"1.4",
"1.6",
"1.7",
"1.8",
"2.0",
"2.2",
"2.4",
"2.6",
"2.8",
"3.1",
"3.4",
"3.7",
"4.0",
"4.4",
"4.8",
"5.2",
"5.6",
"6.2",
"6.8",
"7.3",
"8.0",
"8.7",
"9.6",
"10",
"11",
"12",
"14",
"14",
"16",
"17",
"18",
"6.7"
};
/* Observations from my HDV Camera (Canon HV20 Pal)
* FIXME : replace with with code once we've figured out the algorithm.
* Shutter speed 0x4f 0x50
* ------------------------------------
* 1/6 F3 95
* 1/8 90 91
* 1/12 FA 8A
* 1/15 C8 88
* 1/24 7D 85
* 1/30 64 84
* 1/48 BE 82
* 1/60 32 82
* 1/100 51 81
* 1/250 87 80
* 1/500 43 80
* 1/1000 22 80
* 1/2000 11 80
*/
typedef struct
{
guint vala, valb, shutter;
} Shutter_t;
static Shutter_t shutter_table[] = {
{0xf3, 0x95, 6},
{0x90, 0x91, 8},
{0xfa, 0x8a, 12},
{0xc8, 0x88, 15},
{0x7d, 0x85, 24},
{0x64, 0x84, 30},
{0xbe, 0x82, 48},
{0x32, 0x82, 60},
{0x51, 0x81, 100},
{0x87, 0x80, 250},
{0x43, 0x80, 500},
{0x22, 0x80, 1000},
{0x11, 0x80, 2000}
};
/* Binary-coded decimal reading macro */
#define BCD(c) ( ((((c) >> 4) & 0x0f) * 10) + ((c) & 0x0f) )
/* Same as before, but with a mask */
#define BCD_M(c, mask) (BCD ((c) & (mask)))
/* the capabilities of the inputs and outputs.
*
* describe the real formats here.
@ -124,11 +208,122 @@ gst_hdvparse_init (GstHDVParse * filter, GstHDVParseClass * klass)
gst_base_transform_set_passthrough (transform, TRUE);
}
static guint
get_shutter_speed (guint8 vala, guint8 valb)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (shutter_table); i++)
if (shutter_table[i].vala == vala && shutter_table[i].valb == valb)
return shutter_table[i].shutter;
GST_WARNING ("Unknown shutter speed ! vala:0x%02x, valb:0x%02x", vala, valb);
return 0;
}
static void
gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
{
GST_MEMDUMP_OBJECT (filter, "BUFFER", GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf));
guint8 *data = GST_BUFFER_DATA (buf);
guint apertured, shutter;
gfloat gain;
gboolean dst = FALSE;
GstStructure *str;
GstMessage *msg;
GST_MEMDUMP_OBJECT (filter, "BUFFER", data, GST_BUFFER_SIZE (buf));
str = gst_structure_empty_new ("HDV");
/* 0x1f - 0x23 : TimeCode */
if (data[0x1f] != 0xff) {
guint8 tframe, tsec, tmin, thour;
gchar *timecode = NULL;
tframe = BCD (data[0x1f] & 0x3f);
tsec = BCD (data[0x20] & 0x7f);
tmin = BCD (data[0x21] & 0x7f);
thour = BCD (data[0x22] & 0x3f);
timecode =
g_strdup_printf ("%01d:%02d:%02d.%02d", thour, tmin, tsec, tframe);
gst_structure_set (str, "timecode", G_TYPE_STRING, timecode, NULL);
g_free (timecode);
GST_LOG_OBJECT (filter, timecode);
}
/* 0x23 : Timezone / Dailight Saving Time */
/* 0x24 - 0x2a : Original time */
if (data[0x23] != 0xff) {
GDate *date = NULL;
guint tzone = 0;
guint day, month, year, hour, min, sec;
gchar *datetime;
tzone = data[0x23];
dst = !(tzone & 0x80);
tzone =
BCD (tzone & 0x1f) > 12 ? BCD (tzone & 0x1f) - 12 : BCD (tzone & 0x1f);
GST_LOG_OBJECT (filter, "TimeZone : %d, DST : %d", tzone, dst);
day = BCD_M (data[0x24], 0x3f);
month = BCD_M (data[0x25], 0x1f);
year = BCD (data[0x26]);
if (year > 90)
year += 1900;
else
year += 2000;
/* 0x27: ??? */
sec = BCD_M (data[0x28], 0x7f);
min = BCD_M (data[0x29], 0x7f);
hour = BCD_M (data[0x2a], 0x3f);
/* FIXME : we need a date/time object ! */
date = g_date_new_dmy (day, month, year);
datetime =
g_strdup_printf ("%02d/%02d/%02d %02d:%02d:%02d", day, month, year,
hour, min, sec);
gst_structure_set (str, "date", GST_TYPE_DATE, date, "recording-time",
G_TYPE_STRING, datetime, NULL);
g_free (datetime);
GST_LOG_OBJECT (filter, datetime);
}
/* 0x2b : Various flags, including scene-change */
if (!((data[0x2b] & 0x20) >> 5)) {
GST_LOG_OBJECT (filter, "Scene change !");
gst_structure_set (str, "scene-change", G_TYPE_BOOLEAN, TRUE, NULL);
}
/* Check for partials */
if (GST_BUFFER_SIZE (buf) < 0x50) {
goto beach;
}
/* 0x43 : Aperture */
apertured = data[0x43] & 0x3f;
if (apertured < 35) {
GST_LOG_OBJECT (filter, "Aperture : F%s", aperture_table[apertured]);
gst_structure_set (str, "aperture", G_TYPE_STRING,
aperture_table[apertured], NULL);
} else {
GST_LOG_OBJECT (filter, "Aperture : %d", apertured);
}
/* 0x44 : Gain */
gain = ((data[0x44] & 0xf) - 1) * 1.5;
GST_LOG_OBJECT (filter, "Gain : %03f db", gain);
gst_structure_set (str, "gain", G_TYPE_FLOAT, gain, NULL);
/* 0x4f - 0x50 : Shutter */
shutter = get_shutter_speed (data[0x4f], data[0x50]);
GST_LOG_OBJECT (filter, "Shutter speed : 1/%d", shutter);
if (shutter)
gst_structure_set (str, "shutter-speed", GST_TYPE_FRACTION, 1, shutter,
NULL);
beach:
msg = gst_message_new_element (GST_OBJECT (filter), str);
gst_element_post_message (GST_ELEMENT (filter), msg);
return;
}