mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
qtdemux: extract the palette from stsd
Sometimes a palette is inside the stsd, extract it instead of always using the default one
This commit is contained in:
parent
9f73447229
commit
4c97701650
1 changed files with 105 additions and 62 deletions
|
@ -5572,10 +5572,6 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->caps) {
|
if (stream->caps) {
|
||||||
gboolean gray;
|
|
||||||
gint depth, palette_count;
|
|
||||||
const guint32 *palette_data = NULL;
|
|
||||||
|
|
||||||
stream->caps = gst_caps_make_writable (stream->caps);
|
stream->caps = gst_caps_make_writable (stream->caps);
|
||||||
|
|
||||||
gst_caps_set_simple (stream->caps,
|
gst_caps_set_simple (stream->caps,
|
||||||
|
@ -5608,59 +5604,6 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
|
||||||
gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
|
gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
|
||||||
GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
|
GST_TYPE_FRACTION, stream->par_w, stream->par_h, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
depth = stream->bits_per_sample;
|
|
||||||
|
|
||||||
/* more than 32 bits means grayscale */
|
|
||||||
gray = (depth > 32);
|
|
||||||
/* low 32 bits specify the depth */
|
|
||||||
depth &= 0x1F;
|
|
||||||
|
|
||||||
/* different number of palette entries is determined by depth. */
|
|
||||||
palette_count = 0;
|
|
||||||
if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
|
|
||||||
palette_count = (1 << depth);
|
|
||||||
|
|
||||||
switch (palette_count) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
palette_data = ff_qt_default_palette_2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
palette_data = ff_qt_default_palette_4;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
if (gray)
|
|
||||||
palette_data = ff_qt_grayscale_palette_16;
|
|
||||||
else
|
|
||||||
palette_data = ff_qt_default_palette_16;
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
if (gray)
|
|
||||||
palette_data = ff_qt_grayscale_palette_256;
|
|
||||||
else
|
|
||||||
palette_data = ff_qt_default_palette_256;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
|
|
||||||
(_("The video in this file might not play correctly.")),
|
|
||||||
("unsupported palette depth %d", depth));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (palette_data) {
|
|
||||||
if (stream->rgb8_palette)
|
|
||||||
gst_memory_unref (stream->rgb8_palette);
|
|
||||||
stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
|
||||||
(gchar *) palette_data, palette_count * 4, 0, palette_count * 4,
|
|
||||||
NULL, NULL);
|
|
||||||
} else if (palette_count != 0) {
|
|
||||||
GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
|
|
||||||
(NULL), ("Unsupported palette depth %d. Ignoring stream.", depth));
|
|
||||||
|
|
||||||
gst_object_unref (stream->pad);
|
|
||||||
stream->pad = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (stream->subtype == FOURCC_soun) {
|
} else if (stream->subtype == FOURCC_soun) {
|
||||||
if (stream->caps) {
|
if (stream->caps) {
|
||||||
|
@ -6950,7 +6893,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
guint32 tkhd_flags = 0;
|
guint32 tkhd_flags = 0;
|
||||||
guint8 tkhd_version = 0;
|
guint8 tkhd_version = 0;
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
guint value_size, len;
|
guint value_size, stsd_len, len;
|
||||||
guint32 track_id;
|
guint32 track_id;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtdemux, "parse_trak");
|
GST_DEBUG_OBJECT (qtdemux, "parse_trak");
|
||||||
|
@ -7095,19 +7038,21 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
stsd_data = (const guint8 *) stsd->data;
|
stsd_data = (const guint8 *) stsd->data;
|
||||||
|
|
||||||
/* stsd should at least have one entry */
|
/* stsd should at least have one entry */
|
||||||
len = QT_UINT32 (stsd_data);
|
stsd_len = QT_UINT32 (stsd_data);
|
||||||
if (len < 24)
|
if (stsd_len < 24)
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (qtdemux, "stsd len: %d", stsd_len);
|
||||||
|
|
||||||
/* and that entry should fit within stsd */
|
/* and that entry should fit within stsd */
|
||||||
len = QT_UINT32 (stsd_data + 16);
|
len = QT_UINT32 (stsd_data + 16);
|
||||||
if (len > QT_UINT32 (stsd_data) + 16)
|
if (len > stsd_len + 16)
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
GST_LOG_OBJECT (qtdemux, "stsd len: %d", len);
|
|
||||||
|
|
||||||
stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
|
stream->fourcc = fourcc = QT_FOURCC (stsd_data + 16 + 4);
|
||||||
GST_LOG_OBJECT (qtdemux, "stsd type: %" GST_FOURCC_FORMAT,
|
GST_LOG_OBJECT (qtdemux, "stsd type: %" GST_FOURCC_FORMAT,
|
||||||
GST_FOURCC_ARGS (stream->fourcc));
|
GST_FOURCC_ARGS (stream->fourcc));
|
||||||
|
GST_LOG_OBJECT (qtdemux, "stsd type len: %d", len);
|
||||||
|
|
||||||
if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
|
if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi) ||
|
||||||
((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
|
((fourcc & 0xFFFFFF00) == GST_MAKE_FOURCC ('e', 'n', 'c', 0)))
|
||||||
|
@ -7115,6 +7060,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
|
|
||||||
if (stream->subtype == FOURCC_vide) {
|
if (stream->subtype == FOURCC_vide) {
|
||||||
guint32 w = 0, h = 0;
|
guint32 w = 0, h = 0;
|
||||||
|
gboolean gray;
|
||||||
|
gint depth, palette_size, palette_count;
|
||||||
|
guint32 *palette_data = NULL;
|
||||||
|
|
||||||
stream->sampled = TRUE;
|
stream->sampled = TRUE;
|
||||||
|
|
||||||
|
@ -7138,6 +7086,100 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
|
stream->bits_per_sample = QT_UINT16 (stsd_data + offset + 82);
|
||||||
stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
|
stream->color_table_id = QT_UINT16 (stsd_data + offset + 84);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
|
||||||
|
stream->width, stream->height, stream->bits_per_sample,
|
||||||
|
stream->color_table_id);
|
||||||
|
|
||||||
|
depth = stream->bits_per_sample;
|
||||||
|
|
||||||
|
/* more than 32 bits means grayscale */
|
||||||
|
gray = (depth > 32);
|
||||||
|
/* low 32 bits specify the depth */
|
||||||
|
depth &= 0x1F;
|
||||||
|
|
||||||
|
/* different number of palette entries is determined by depth. */
|
||||||
|
palette_count = 0;
|
||||||
|
if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
|
||||||
|
palette_count = (1 << depth);
|
||||||
|
palette_size = palette_count * 4;
|
||||||
|
|
||||||
|
if (stream->color_table_id) {
|
||||||
|
switch (palette_count) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
if (gray)
|
||||||
|
palette_data = g_memdup (ff_qt_grayscale_palette_16, palette_size);
|
||||||
|
else
|
||||||
|
palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
if (gray)
|
||||||
|
palette_data = g_memdup (ff_qt_grayscale_palette_256, palette_size);
|
||||||
|
else
|
||||||
|
palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
|
||||||
|
(_("The video in this file might not play correctly.")),
|
||||||
|
("unsupported palette depth %d", depth));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gint i, j, start, end;
|
||||||
|
|
||||||
|
if (len < 94)
|
||||||
|
goto corrupt_file;
|
||||||
|
|
||||||
|
/* read table */
|
||||||
|
start = QT_UINT32 (stsd_data + offset + 86);
|
||||||
|
palette_count = QT_UINT16 (stsd_data + offset + 90);
|
||||||
|
end = QT_UINT16 (stsd_data + offset + 92);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
|
||||||
|
start, end, palette_count);
|
||||||
|
|
||||||
|
if (end > 255)
|
||||||
|
end = 255;
|
||||||
|
if (start > end)
|
||||||
|
start = end;
|
||||||
|
|
||||||
|
if (len < 94 + (end - start) * 8)
|
||||||
|
goto corrupt_file;
|
||||||
|
|
||||||
|
/* palette is always the same size */
|
||||||
|
palette_data = g_malloc0 (256 * 4);
|
||||||
|
palette_size = 256 * 4;
|
||||||
|
|
||||||
|
for (j = 0, i = start; i <= end; j++, i++) {
|
||||||
|
guint32 a, r, g, b;
|
||||||
|
|
||||||
|
a = QT_UINT16 (stsd_data + offset + 94 + (j * 8));
|
||||||
|
r = QT_UINT16 (stsd_data + offset + 96 + (j * 8));
|
||||||
|
g = QT_UINT16 (stsd_data + offset + 98 + (j * 8));
|
||||||
|
b = QT_UINT16 (stsd_data + offset + 100 + (j * 8));
|
||||||
|
|
||||||
|
palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
|
||||||
|
(g & 0xff00) | (b >> 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palette_data) {
|
||||||
|
if (stream->rgb8_palette)
|
||||||
|
gst_memory_unref (stream->rgb8_palette);
|
||||||
|
stream->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
||||||
|
palette_data, palette_size, 0, palette_size, palette_data, g_free);
|
||||||
|
} else if (palette_count != 0) {
|
||||||
|
GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
|
||||||
|
(NULL), ("Unsupported palette depth %d", depth));
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (qtdemux, "frame count: %u",
|
GST_LOG_OBJECT (qtdemux, "frame count: %u",
|
||||||
QT_UINT16 (stsd_data + offset + 48));
|
QT_UINT16 (stsd_data + offset + 48));
|
||||||
|
|
||||||
|
@ -9997,6 +10039,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
|
case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
|
||||||
caps = gst_caps_new_empty_simple ("video/x-raw");
|
caps = gst_caps_new_empty_simple ("video/x-raw");
|
||||||
gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
|
gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
|
||||||
|
_codec ("Windows Raw RGB");
|
||||||
break;
|
break;
|
||||||
case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
|
case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue