hdvparse: Emit a GST_MESSAGE_ELEMENT with some goodness in it.

This commit is contained in:
Edward Hervey 2009-06-05 20:22:17 +02:00
parent 37254a21f4
commit 0e1ee9031a

View file

@ -69,7 +69,7 @@ enum
/* If set to 1, then extra validation will be applied to check /* If set to 1, then extra validation will be applied to check
* for complete spec compliance wherever applicable. */ * for complete spec compliance wherever applicable. */
#define VALIDATE 1 #define VALIDATE 0
/* Binary-coded decimal reading macro */ /* Binary-coded decimal reading macro */
#define BCD(c) ( ((((c) >> 4) & 0x0f) * 10) + ((c) & 0x0f) ) #define BCD(c) ( ((((c) >> 4) & 0x0f) * 10) + ((c) & 0x0f) )
@ -186,7 +186,8 @@ sfr_to_framerate (guint8 sfr)
} }
static GstFlowReturn static GstFlowReturn
parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size) parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size,
GstStructure * st)
{ {
guint64 offs = 1; guint64 offs = 1;
@ -208,12 +209,15 @@ parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG (" Iris position %d (0x%x)", irispos, irispos); GST_LOG (" Iris position %d (0x%x)", irispos, irispos);
/* Iris position = 2 ^ (IP/8) (for 0 < IP < 0x3C) */ /* Iris position = 2 ^ (IP/8) (for 0 < IP < 0x3C) */
if (irispos < 0x3c) if (irispos < 0x3c) {
GST_LOG (" IRIS F%0.2f", powf (2.0, (((float) irispos) / 8.0))); GST_LOG (" IRIS F%0.2f", powf (2.0, (((float) irispos) / 8.0)));
else if (irispos == 0x3d) gst_structure_set (st, "aperture-fnumber", G_TYPE_FLOAT,
powf (2.0, (((float) irispos) / 8.0)), NULL);
} else if (irispos == 0x3d) {
GST_LOG (" IRIS < 1.0"); GST_LOG (" IRIS < 1.0");
else if (irispos == 0x3e) } else if (irispos == 0x3e) {
GST_LOG (" IRIS closed"); GST_LOG (" IRIS closed");
}
/* AE Mode: /* AE Mode:
* 0 : Full automatic * 0 : Full automatic
@ -227,8 +231,9 @@ parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG (" AGC: %d (0x%x)", agc, agc); GST_LOG (" AGC: %d (0x%x)", agc, agc);
if (agc < 0xd) { if (agc < 0xd) {
GST_LOG (" Gain:%02.2fdB", (agc - 1.0) * 1.5); /* This is what the spec says.. but I'm not seeing the same on my camera :( */
GST_LOG (" Gain:%02.2fdB", (agc * 3.0) - 3); GST_LOG (" Gain:%02.2fdB", (agc * 3.0) - 3.0);
gst_structure_set (st, "gain", G_TYPE_FLOAT, (agc * 3.0) - 3.0, NULL);
} }
/* White balance mode /* White balance mode
* 0 : Automatic * 0 : Automatic
@ -301,10 +306,12 @@ parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size)
speedint = speedint / 10 * 10; speedint = speedint / 10 * 10;
GST_LOG (" Shutter speed : 1/%d", speedint); GST_LOG (" Shutter speed : 1/%d", speedint);
gst_structure_set (st, "shutter-speed", GST_TYPE_FRACTION,
1, speedint, NULL);
} }
break; break;
default: default:
gst_util_dump_mem (data + offs, 5); GST_MEMDUMP ("Unknown pack", data + offs, 5);
break; break;
} }
size -= 5; size -= 5;
@ -314,7 +321,8 @@ parse_dv_multi_pack (GstHDVParse * filter, guint8 * data, guint64 size)
} }
static GstFlowReturn static GstFlowReturn
parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size) parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size,
GstStructure * st)
{ {
guint32 etn, bitrate; guint32 etn, bitrate;
guint8 nbframes, data_h, hdr_size, sfr, sdm; guint8 nbframes, data_h, hdr_size, sfr, sdm;
@ -405,6 +413,9 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG_OBJECT (filter, " Source Frame Rate : %s (0x%x)", GST_LOG_OBJECT (filter, " Source Frame Rate : %s (0x%x)",
sfr_to_framerate (sfr), sfr); sfr_to_framerate (sfr), sfr);
gst_structure_set (st, "DTS", G_TYPE_UINT64, MPEGTIME_TO_GSTTIME (dts),
"interlaced", G_TYPE_BOOLEAN, !pf, NULL);
/* Search Data Mode /* Search Data Mode
* --------------------------------- * ---------------------------------
* 15 | Search Data Mode | * 15 | Search Data Mode |
@ -482,7 +493,6 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
(chroma == 0x1) ? "4:2:0" : "RESERVED", chroma); (chroma == 0x1) ? "4:2:0" : "RESERVED", chroma);
GST_LOG_OBJECT (filter, " GOP N/M : %d / %d", gop_n, gop_m); GST_LOG_OBJECT (filter, " GOP N/M : %d / %d", gop_n, gop_m);
/* data availability /* data availability
* --------------------------------- * ---------------------------------
* 29 | 0 | 0 | 0 | 0 | 0 |PE2|PE1|PE0| * 29 | 0 | 0 | 0 | 0 | 0 |PE2|PE1|PE0|
@ -494,6 +504,8 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
if (data[29] & 0x1) { if (data[29] & 0x1) {
guint8 fr, sec, min, hr; guint8 fr, sec, min, hr;
gboolean bf, df; gboolean bf, df;
gchar *ttcs;
/* HD2 TTC /* HD2 TTC
* --------------------------------- * ---------------------------------
* 30 |BF |DF |Tens Fr|Units of Frames| * 30 |BF |DF |Tens Fr|Units of Frames|
@ -513,12 +525,19 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
hr = BCD (data[33] & 0x3f); hr = BCD (data[33] & 0x3f);
GST_LOG_OBJECT (filter, " HD2 Title Time Code"); GST_LOG_OBJECT (filter, " HD2 Title Time Code");
GST_LOG_OBJECT (filter, " BF:%d, Drop Frame:%d", bf, df); GST_LOG_OBJECT (filter, " BF:%d, Drop Frame:%d", bf, df);
GST_LOG_OBJECT (filter, " Timecode %02d:%02d:%02d.%02d", hr, min, sec, fr); ttcs = g_strdup_printf ("%02d:%02d:%02d.%02d", hr, min, sec, fr);
GST_LOG_OBJECT (filter, " Timecode %s", ttcs);
/* FIXME : Use framerate information from above to convert to GstClockTime */ /* FIXME : Use framerate information from above to convert to GstClockTime */
gst_structure_set (st, "title-time-code", G_TYPE_STRING, ttcs, NULL);
g_free (ttcs);
} }
if (data[29] & 0x2) { if (data[29] & 0x2) {
gboolean ds, tm; gboolean ds, tm;
guint8 tz, day, dow, month, year; guint8 tz, day, dow, month, year;
GDate *date;
/* REC DATE /* REC DATE
* --------------------------------- * ---------------------------------
* 34 |DS |TM |Tens TZ|Units of TimeZn| * 34 |DS |TM |Tens TZ|Units of TimeZn|
@ -542,9 +561,17 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG_OBJECT (filter, " ds:%d, tm:%d", ds, tm); GST_LOG_OBJECT (filter, " ds:%d, tm:%d", ds, tm);
GST_LOG_OBJECT (filter, " Timezone: %d", tz); GST_LOG_OBJECT (filter, " Timezone: %d", tz);
GST_LOG_OBJECT (filter, " Date: %d %02d/%02d/%04d", dow, day, month, year); GST_LOG_OBJECT (filter, " Date: %d %02d/%02d/%04d", dow, day, month, year);
date = g_date_new_dmy (day, month, year);
gst_structure_set (st, "date", GST_TYPE_DATE, date,
"timezone", G_TYPE_INT, tz,
"daylight-saving", G_TYPE_BOOLEAN, ds, NULL);
g_date_free (date);
} }
if (data[29] & 0x4) { if (data[29] & 0x4) {
guint8 fr, sec, min, hr; guint8 fr, sec, min, hr;
gchar *times;
/* REC TIME /* REC TIME
* --------------------------------- * ---------------------------------
* 38 | 1 | 1 |Tens Fr|Units of Frames| * 38 | 1 | 1 |Tens Fr|Units of Frames|
@ -560,7 +587,10 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
sec = BCD (data[39] & 0x7f); sec = BCD (data[39] & 0x7f);
min = BCD (data[40] & 0x7f); min = BCD (data[40] & 0x7f);
hr = BCD (data[41] & 0x3f); hr = BCD (data[41] & 0x3f);
times = g_strdup_printf ("%02d:%02d:%02d", hr, min, sec);
GST_LOG_OBJECT (filter, " REC TIME %02d:%02d:%02d.%02d", hr, min, sec, fr); GST_LOG_OBJECT (filter, " REC TIME %02d:%02d:%02d.%02d", hr, min, sec, fr);
gst_structure_set (st, "time", G_TYPE_STRING, times, NULL);
g_free (times);
} }
/* MISC /* MISC
@ -578,6 +608,8 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG_OBJECT (filter, " ABST : %s", GST_LOG_OBJECT (filter, " ABST : %s",
(abst == 0) ? "DISCONTINUITY" : "NO DISCONTINUITY"); (abst == 0) ? "DISCONTINUITY" : "NO DISCONTINUITY");
gst_structure_set (st, "recording-start-point", G_TYPE_BOOLEAN, !recst, NULL);
/* Extended DV Pack #1 /* Extended DV Pack #1
* 43 - 47 * 43 - 47
*/ */
@ -598,7 +630,8 @@ parse_video_frame (GstHDVParse * filter, guint8 * data, guint64 size)
} }
static GstFlowReturn static GstFlowReturn
parse_audio_frame (GstHDVParse * filter, guint8 * data, guint64 size) parse_audio_frame (GstHDVParse * filter, guint8 * data, guint64 size,
GstStructure * st)
{ {
guint32 etn; guint32 etn;
guint8 nbmute, nbaau; guint8 nbmute, nbaau;
@ -718,6 +751,10 @@ parse_audio_frame (GstHDVParse * filter, guint8 * data, guint64 size)
GST_LOG_OBJECT (filter, " CGMS : 0x%x", cgms); GST_LOG_OBJECT (filter, " CGMS : 0x%x", cgms);
GST_LOG_OBJECT (filter, " Recording Start Point %s", GST_LOG_OBJECT (filter, " Recording Start Point %s",
(recst) ? "ABSENT" : "PRESENT"); (recst) ? "ABSENT" : "PRESENT");
gst_structure_set (st, "PTS", G_TYPE_UINT64, MPEGTIME_TO_GSTTIME (pts),
"recording-start-point", G_TYPE_BOOLEAN, !recst, NULL);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -728,6 +765,7 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
guint8 *data = GST_BUFFER_DATA (buf); guint8 *data = GST_BUFFER_DATA (buf);
guint64 offs = 0; guint64 offs = 0;
guint64 insize = GST_BUFFER_SIZE (buf); guint64 insize = GST_BUFFER_SIZE (buf);
GstStructure *st;
/* Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | /* Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* --------------------------------- * ---------------------------------
@ -753,7 +791,7 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
* 0x7F : AUX-N NULL PACK * 0x7F : AUX-N NULL PACK
*/ */
gst_util_dump_mem (data, insize); st = gst_structure_empty_new ("hdv-aux");
while (res == GST_FLOW_OK && (offs < insize)) { while (res == GST_FLOW_OK && (offs < insize)) {
guint8 kw = data[offs] & 0x7f; guint8 kw = data[offs] & 0x7f;
@ -767,8 +805,10 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
/* Size validation */ /* Size validation */
GST_DEBUG ("kw:0x%x, insize:%d, offs:%d, size:%d", kw, insize, offs, size); GST_DEBUG ("kw:0x%x, insize:%d, offs:%d, size:%d", kw, insize, offs, size);
if (insize < offs + size) if (insize < offs + size) {
return GST_FLOW_ERROR; res = GST_FLOW_ERROR;
goto beach;
}
switch (kw) { switch (kw) {
case 0x01: case 0x01:
@ -780,7 +820,7 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
break; break;
case 0x40: case 0x40:
GST_LOG ("Audio frame pack"); GST_LOG ("Audio frame pack");
res = parse_audio_frame (filter, data + offs + 1, size); res = parse_audio_frame (filter, data + offs + 1, size, st);
offs += size + 2; offs += size + 2;
break; break;
case 0x3f: case 0x3f:
@ -789,7 +829,7 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
break; break;
case 0x44: case 0x44:
GST_LOG ("Video frame pack"); GST_LOG ("Video frame pack");
res = parse_video_frame (filter, data + offs + 1, size); res = parse_video_frame (filter, data + offs + 1, size, st);
offs += size + 2; offs += size + 2;
break; break;
case 0x48: case 0x48:
@ -797,7 +837,7 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
case 0x4A: case 0x4A:
case 0x4B: case 0x4B:
GST_LOG ("DV multi-pack"); GST_LOG ("DV multi-pack");
res = parse_dv_multi_pack (filter, data + offs + 1, size); res = parse_dv_multi_pack (filter, data + offs + 1, size, st);
offs += size + 2; offs += size + 2;
break; break;
default: default:
@ -806,6 +846,15 @@ gst_hdvparse_parse (GstHDVParse * filter, GstBuffer * buf)
} }
} }
beach:
if (gst_structure_n_fields (st)) {
GstMessage *msg;
/* Emit the element message */
msg = gst_message_new_element (GST_OBJECT (filter), st);
gst_element_post_message (GST_ELEMENT (filter), msg);
} else
gst_structure_free (st);
return res; return res;
} }