mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
Merge branch 'master' into 0.11
Conflicts: sys/v4l2/v4l2src_calls.c
This commit is contained in:
commit
4bb2b140e9
15 changed files with 48 additions and 5760 deletions
|
@ -963,9 +963,9 @@ AG_GST_CHECK_FEATURE(WAVPACK, [wavpack plug-in], wavpack, [
|
|||
AC_SUBST(WAVPACK_LIBS)
|
||||
])
|
||||
|
||||
dnl *** qtdemux & id3demux & matroska prefer to have zlib ***
|
||||
dnl *** qtdemux & matroska prefer to have zlib ***
|
||||
translit(dnm, m, l) AM_CONDITIONAL(USE_ZLIB, true)
|
||||
AG_GST_CHECK_FEATURE(ZLIB, [zlib support for id3demux/qtdemux/matroska],, [
|
||||
AG_GST_CHECK_FEATURE(ZLIB, [zlib support for qtdemux/matroska],, [
|
||||
AG_GST_CHECK_LIBHEADER(ZLIB,
|
||||
z, uncompress,, zlib.h, [
|
||||
HAVE_ZLIB="yes"
|
||||
|
|
|
@ -355,12 +355,12 @@ gst_jack_ring_buffer_open_device (GstRingBuffer * buf)
|
|||
/* ERRORS */
|
||||
could_not_open:
|
||||
{
|
||||
if (status & JackServerFailed) {
|
||||
if (status & (JackServerFailed | JackFailure)) {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
|
||||
(_("Jack server not found")),
|
||||
("Cannot connect to the Jack server (status %d)", status));
|
||||
} else {
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_WRITE,
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
|
||||
(NULL), ("Jack client open error (status %d)", status));
|
||||
}
|
||||
return FALSE;
|
||||
|
|
|
@ -577,7 +577,7 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
|
|||
buffer = frame->buffer;
|
||||
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
|
||||
|
||||
if (size <= flacparse->min_framesize)
|
||||
if (size < flacparse->min_framesize)
|
||||
goto need_more;
|
||||
|
||||
header_ret =
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
plugin_LTLIBRARIES = libgstid3demux.la
|
||||
|
||||
libgstid3demux_la_SOURCES = gstid3demux.c id3tags.c id3v2frames.c
|
||||
libgstid3demux_la_SOURCES = gstid3demux.c
|
||||
libgstid3demux_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
libgstid3demux_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_MAJORMINOR@ \
|
||||
-lgstpbutils-@GST_MAJORMINOR@ $(GST_BASE_LIBS) $(ZLIB_LIBS)
|
||||
-lgstpbutils-@GST_MAJORMINOR@ $(GST_BASE_LIBS)
|
||||
libgstid3demux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstid3demux_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
noinst_HEADERS = gstid3demux.h id3tags.h
|
||||
noinst_HEADERS = gstid3demux.h
|
||||
|
||||
Android.mk: Makefile.am $(BUILT_SOURCES)
|
||||
androgenizer \
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "gstid3demux.h"
|
||||
#include "id3tags.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -68,6 +67,9 @@ enum
|
|||
GST_DEBUG_CATEGORY (id3demux_debug);
|
||||
#define GST_CAT_DEFAULT (id3demux_debug)
|
||||
|
||||
#define ID3V1_TAG_SIZE 128
|
||||
#define ID3V2_HDR_SIZE GST_TAG_ID3V2_HEADER_SIZE
|
||||
|
||||
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
|
@ -142,7 +144,7 @@ gst_id3demux_identify_tag (GstTagDemux * demux, GstBuffer * buf,
|
|||
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3')
|
||||
goto no_marker;
|
||||
|
||||
*tag_size = id3demux_calc_id3v2_tag_size (buf);
|
||||
*tag_size = gst_tag_get_id3v2_tag_size (buf);
|
||||
} else {
|
||||
if (data[0] != 'T' || data[1] != 'A' || data[2] != 'G')
|
||||
goto no_marker;
|
||||
|
@ -178,11 +180,10 @@ gst_id3demux_parse_tag (GstTagDemux * demux, GstBuffer * buffer,
|
|||
gboolean start_tag, guint * tag_size, GstTagList ** tags)
|
||||
{
|
||||
if (start_tag) {
|
||||
ID3TagsResult res; /* FIXME: make id3tags.c return tagmuxresult values */
|
||||
*tag_size = gst_tag_get_id3v2_tag_size (buffer);
|
||||
*tags = gst_tag_list_from_id3v2_tag (buffer);
|
||||
|
||||
res = id3demux_read_id3v2_tag (buffer, tag_size, tags);
|
||||
|
||||
if (G_LIKELY (res == ID3TAGS_READ_TAG)) {
|
||||
if (G_LIKELY (*tags != NULL)) {
|
||||
gst_id3demux_add_container_format (*tags);
|
||||
return GST_TAG_DEMUX_RESULT_OK;
|
||||
} else {
|
||||
|
@ -276,11 +277,6 @@ plugin_init (GstPlugin * plugin)
|
|||
|
||||
gst_tag_register_musicbrainz_tags ();
|
||||
|
||||
/* ensure private tag is registered */
|
||||
gst_tag_register (GST_ID3_DEMUX_TAG_ID3V2_FRAME, GST_TAG_FLAG_META,
|
||||
GST_TYPE_BUFFER, "ID3v2 frame", "unparsed id3v2 tag frame",
|
||||
gst_tag_merge_use_first);
|
||||
|
||||
return gst_element_register (plugin, "id3demux",
|
||||
GST_RANK_PRIMARY, GST_TYPE_ID3DEMUX);
|
||||
}
|
||||
|
|
|
@ -1,554 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
|
||||
/* Copyright 2005 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
* Copyright 2002,2003 Scott Wheeler <wheeler@kde.org> (portions from taglib)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/tag/tag.h>
|
||||
|
||||
#include "id3tags.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (id3demux_debug);
|
||||
#define GST_CAT_DEFAULT (id3demux_debug)
|
||||
|
||||
#define HANDLE_INVALID_SYNCSAFE
|
||||
static ID3TagsResult
|
||||
id3demux_id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size);
|
||||
|
||||
guint
|
||||
read_synch_uint (const guint8 * data, guint size)
|
||||
{
|
||||
gint i;
|
||||
guint result = 0;
|
||||
gint invalid = 0;
|
||||
|
||||
g_assert (size <= 4);
|
||||
|
||||
size--;
|
||||
for (i = 0; i <= size; i++) {
|
||||
invalid |= data[i] & 0x80;
|
||||
result |= (data[i] & 0x7f) << ((size - i) * 7);
|
||||
}
|
||||
|
||||
#ifdef HANDLE_INVALID_SYNCSAFE
|
||||
if (invalid) {
|
||||
GST_WARNING ("Invalid synch-safe integer in ID3v2 frame "
|
||||
"- using the actual value instead");
|
||||
result = 0;
|
||||
for (i = 0; i <= size; i++) {
|
||||
result |= data[i] << ((size - i) * 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
guint
|
||||
id3demux_calc_id3v2_tag_size (GstBuffer * buf)
|
||||
{
|
||||
guint8 *data, flags;
|
||||
guint size;
|
||||
|
||||
g_assert (buf != NULL);
|
||||
g_assert (GST_BUFFER_SIZE (buf) >= ID3V2_HDR_SIZE);
|
||||
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
|
||||
/* Check for 'ID3' string at start of buffer */
|
||||
if (data[0] != 'I' || data[1] != 'D' || data[2] != '3') {
|
||||
GST_DEBUG ("No ID3v2 tag in data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the flags */
|
||||
flags = data[5];
|
||||
|
||||
/* Read the size from the header */
|
||||
size = read_synch_uint (data + 6, 4);
|
||||
if (size == 0)
|
||||
return ID3V2_HDR_SIZE;
|
||||
|
||||
size += ID3V2_HDR_SIZE;
|
||||
|
||||
/* Expand the read size to include a footer if there is one */
|
||||
if ((flags & ID3V2_HDR_FLAG_FOOTER))
|
||||
size += 10;
|
||||
|
||||
GST_DEBUG ("ID3v2 tag, size: %u bytes", size);
|
||||
return size;
|
||||
}
|
||||
|
||||
guint8 *
|
||||
id3demux_ununsync_data (const guint8 * unsync_data, guint32 * size)
|
||||
{
|
||||
const guint8 *end;
|
||||
guint8 *out, *uu;
|
||||
guint out_size;
|
||||
|
||||
uu = out = g_malloc (*size);
|
||||
|
||||
for (end = unsync_data + *size; unsync_data < end - 1; ++unsync_data, ++uu) {
|
||||
*uu = *unsync_data;
|
||||
if (G_UNLIKELY (*unsync_data == 0xff && *(unsync_data + 1) == 0x00))
|
||||
++unsync_data;
|
||||
}
|
||||
|
||||
/* take care of last byte (if last two bytes weren't 0xff 0x00) */
|
||||
if (unsync_data < end) {
|
||||
*uu = *unsync_data;
|
||||
++uu;
|
||||
}
|
||||
|
||||
out_size = uu - out;
|
||||
GST_DEBUG ("size after un-unsyncing: %u (before: %u)", out_size, *size);
|
||||
|
||||
*size = out_size;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* caller must pass buffer with full ID3 tag */
|
||||
ID3TagsResult
|
||||
id3demux_read_id3v2_tag (GstBuffer * buffer, guint * id3v2_size,
|
||||
GstTagList ** tags)
|
||||
{
|
||||
guint8 *data, *uu_data = NULL;
|
||||
guint read_size;
|
||||
ID3TagsWorking work;
|
||||
guint8 flags;
|
||||
ID3TagsResult result;
|
||||
guint16 version;
|
||||
|
||||
read_size = id3demux_calc_id3v2_tag_size (buffer);
|
||||
|
||||
if (id3v2_size)
|
||||
*id3v2_size = read_size;
|
||||
|
||||
/* Ignore tag if it has no frames attached, but skip the header then */
|
||||
if (read_size <= ID3V2_HDR_SIZE)
|
||||
return ID3TAGS_BROKEN_TAG;
|
||||
|
||||
data = GST_BUFFER_DATA (buffer);
|
||||
|
||||
/* Read the version */
|
||||
version = GST_READ_UINT16_BE (data + 3);
|
||||
|
||||
/* Read the flags */
|
||||
flags = data[5];
|
||||
|
||||
/* Validate the version. At the moment, we only support up to 2.4.0 */
|
||||
if (ID3V2_VER_MAJOR (version) > 4 || ID3V2_VER_MINOR (version) > 0) {
|
||||
GST_WARNING ("ID3v2 tag is from revision 2.%d.%d, "
|
||||
"but decoder only supports 2.%d.%d. Ignoring as per spec.",
|
||||
version >> 8, version & 0xff, ID3V2_VERSION >> 8, ID3V2_VERSION & 0xff);
|
||||
return ID3TAGS_BROKEN_TAG;
|
||||
}
|
||||
|
||||
GST_DEBUG ("ID3v2 header flags: %s %s %s %s",
|
||||
(flags & ID3V2_HDR_FLAG_UNSYNC) ? "UNSYNC" : "",
|
||||
(flags & ID3V2_HDR_FLAG_EXTHDR) ? "EXTENDED_HEADER" : "",
|
||||
(flags & ID3V2_HDR_FLAG_EXPERIMENTAL) ? "EXPERIMENTAL" : "",
|
||||
(flags & ID3V2_HDR_FLAG_FOOTER) ? "FOOTER" : "");
|
||||
|
||||
/* This shouldn't really happen! Caller should have checked first */
|
||||
if (GST_BUFFER_SIZE (buffer) < read_size) {
|
||||
GST_DEBUG
|
||||
("Found ID3v2 tag with revision 2.%d.%d - need %u more bytes to read",
|
||||
version >> 8, version & 0xff,
|
||||
(guint) (read_size - GST_BUFFER_SIZE (buffer)));
|
||||
return ID3TAGS_MORE_DATA; /* Need more data to decode with */
|
||||
}
|
||||
|
||||
GST_DEBUG ("Reading ID3v2 tag with revision 2.%d.%d of size %u", version >> 8,
|
||||
version & 0xff, read_size);
|
||||
|
||||
g_return_val_if_fail (tags != NULL, ID3TAGS_READ_TAG);
|
||||
|
||||
GST_MEMDUMP ("ID3v2 tag", GST_BUFFER_DATA (buffer), read_size);
|
||||
|
||||
memset (&work, 0, sizeof (ID3TagsWorking));
|
||||
work.buffer = buffer;
|
||||
work.hdr.version = version;
|
||||
work.hdr.size = read_size;
|
||||
work.hdr.flags = flags;
|
||||
work.hdr.frame_data = GST_BUFFER_DATA (buffer) + ID3V2_HDR_SIZE;
|
||||
if (flags & ID3V2_HDR_FLAG_FOOTER)
|
||||
work.hdr.frame_data_size = read_size - ID3V2_HDR_SIZE - 10;
|
||||
else
|
||||
work.hdr.frame_data_size = read_size - ID3V2_HDR_SIZE;
|
||||
|
||||
/* in v2.3 the frame sizes are not syncsafe, so the entire tag had to be
|
||||
* unsynced. In v2.4 the frame sizes are syncsafe so it's just the frame
|
||||
* data that needs un-unsyncing, but not the frame headers. */
|
||||
if ((flags & ID3V2_HDR_FLAG_UNSYNC) != 0 && ID3V2_VER_MAJOR (version) <= 3) {
|
||||
GST_DEBUG ("Un-unsyncing entire tag");
|
||||
uu_data = id3demux_ununsync_data (work.hdr.frame_data,
|
||||
&work.hdr.frame_data_size);
|
||||
work.hdr.frame_data = uu_data;
|
||||
GST_MEMDUMP ("ID3v2 tag (un-unsyced)", uu_data, work.hdr.frame_data_size);
|
||||
}
|
||||
|
||||
result = id3demux_id3v2_frames_to_tag_list (&work, work.hdr.frame_data_size);
|
||||
|
||||
*tags = work.tags;
|
||||
|
||||
g_free (uu_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static guint
|
||||
id3demux_id3v2_frame_hdr_size (guint id3v2ver)
|
||||
{
|
||||
/* ID3v2 < 2.3.0 only had 6 byte header */
|
||||
switch (ID3V2_VER_MAJOR (id3v2ver)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return 6;
|
||||
case 3:
|
||||
case 4:
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
static const gchar *obsolete_frame_ids[] = {
|
||||
"CRM", "EQU", "LNK", "RVA", "TIM", "TSI", /* From 2.2 */
|
||||
"EQUA", "RVAD", "TIME", "TRDA", "TSIZ", /* From 2.3 */
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct ID3v2FrameIDConvert
|
||||
{
|
||||
const gchar *orig;
|
||||
const gchar *new;
|
||||
} frame_id_conversions[] = {
|
||||
/* 2.3.x frames */
|
||||
{
|
||||
"TORY", "TDOR"}, {
|
||||
"TYER", "TDRC"},
|
||||
/* 2.2.x frames */
|
||||
{
|
||||
"BUF", "RBUF"}, {
|
||||
"CNT", "PCNT"}, {
|
||||
"COM", "COMM"}, {
|
||||
"CRA", "AENC"}, {
|
||||
"ETC", "ETCO"}, {
|
||||
"GEO", "GEOB"}, {
|
||||
"IPL", "TIPL"}, {
|
||||
"MCI", "MCDI"}, {
|
||||
"MLL", "MLLT"}, {
|
||||
"PIC", "APIC"}, {
|
||||
"POP", "POPM"}, {
|
||||
"REV", "RVRB"}, {
|
||||
"SLT", "SYLT"}, {
|
||||
"STC", "SYTC"}, {
|
||||
"TAL", "TALB"}, {
|
||||
"TBP", "TBPM"}, {
|
||||
"TCM", "TCOM"}, {
|
||||
"TCO", "TCON"}, {
|
||||
"TCR", "TCOP"}, {
|
||||
"TDA", "TDAT"}, { /* obsolete, but we need to parse it anyway */
|
||||
"TDY", "TDLY"}, {
|
||||
"TEN", "TENC"}, {
|
||||
"TFT", "TFLT"}, {
|
||||
"TKE", "TKEY"}, {
|
||||
"TLA", "TLAN"}, {
|
||||
"TLE", "TLEN"}, {
|
||||
"TMT", "TMED"}, {
|
||||
"TOA", "TOAL"}, {
|
||||
"TOF", "TOFN"}, {
|
||||
"TOL", "TOLY"}, {
|
||||
"TOR", "TDOR"}, {
|
||||
"TOT", "TOAL"}, {
|
||||
"TP1", "TPE1"}, {
|
||||
"TP2", "TPE2"}, {
|
||||
"TP3", "TPE3"}, {
|
||||
"TP4", "TPE4"}, {
|
||||
"TPA", "TPOS"}, {
|
||||
"TPB", "TPUB"}, {
|
||||
"TRC", "TSRC"}, {
|
||||
"TRD", "TDRC"}, {
|
||||
"TRK", "TRCK"}, {
|
||||
"TSS", "TSSE"}, {
|
||||
"TT1", "TIT1"}, {
|
||||
"TT2", "TIT2"}, {
|
||||
"TT3", "TIT3"}, {
|
||||
"TXT", "TOLY"}, {
|
||||
"TXX", "TXXX"}, {
|
||||
"TYE", "TDRC"}, {
|
||||
"UFI", "UFID"}, {
|
||||
"ULT", "USLT"}, {
|
||||
"WAF", "WOAF"}, {
|
||||
"WAR", "WOAR"}, {
|
||||
"WAS", "WOAS"}, {
|
||||
"WCM", "WCOM"}, {
|
||||
"WCP", "WCOP"}, {
|
||||
"WPB", "WPUB"}, {
|
||||
"WXX", "WXXX"}, {
|
||||
NULL, NULL}
|
||||
};
|
||||
|
||||
static gboolean
|
||||
convert_fid_to_v240 (gchar * frame_id)
|
||||
{
|
||||
gint i = 0;
|
||||
|
||||
while (obsolete_frame_ids[i] != NULL) {
|
||||
if (strncmp (frame_id, obsolete_frame_ids[i], 5) == 0)
|
||||
return TRUE;
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (frame_id_conversions[i].orig != NULL) {
|
||||
if (strncmp (frame_id, frame_id_conversions[i].orig, 5) == 0) {
|
||||
strcpy (frame_id, frame_id_conversions[i].new);
|
||||
return FALSE;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* add unknown or unhandled ID3v2 frames to the taglist as binary blobs */
|
||||
static void
|
||||
id3demux_add_id3v2_frame_blob_to_taglist (ID3TagsWorking * work, guint size)
|
||||
{
|
||||
GstBuffer *blob;
|
||||
GstCaps *caps;
|
||||
guint8 *frame_data;
|
||||
gchar *media_type;
|
||||
guint frame_size, header_size;
|
||||
guint i;
|
||||
|
||||
switch (ID3V2_VER_MAJOR (work->hdr.version)) {
|
||||
case 1:
|
||||
case 2:
|
||||
header_size = 3 + 3;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
header_size = 4 + 4 + 2;
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
frame_data = work->hdr.frame_data - header_size;
|
||||
frame_size = size + header_size;
|
||||
|
||||
blob = gst_buffer_new_and_alloc (frame_size);
|
||||
memcpy (GST_BUFFER_DATA (blob), frame_data, frame_size);
|
||||
|
||||
/* Sanitize frame id */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!g_ascii_isalnum (frame_data[i]))
|
||||
frame_data[i] = '_';
|
||||
}
|
||||
|
||||
media_type = g_strdup_printf ("application/x-gst-id3v2-%c%c%c%c-frame",
|
||||
g_ascii_tolower (frame_data[0]), g_ascii_tolower (frame_data[1]),
|
||||
g_ascii_tolower (frame_data[2]), g_ascii_tolower (frame_data[3]));
|
||||
caps = gst_caps_new_simple (media_type, "version", G_TYPE_INT,
|
||||
(gint) ID3V2_VER_MAJOR (work->hdr.version), NULL);
|
||||
gst_buffer_set_caps (blob, caps);
|
||||
gst_caps_unref (caps);
|
||||
g_free (media_type);
|
||||
|
||||
/* gst_util_dump_mem (GST_BUFFER_DATA (blob), GST_BUFFER_SIZE (blob)); */
|
||||
|
||||
gst_tag_list_add (work->tags, GST_TAG_MERGE_APPEND,
|
||||
GST_ID3_DEMUX_TAG_ID3V2_FRAME, blob, NULL);
|
||||
gst_buffer_unref (blob);
|
||||
}
|
||||
|
||||
static ID3TagsResult
|
||||
id3demux_id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
|
||||
{
|
||||
guint frame_hdr_size;
|
||||
guint8 *start;
|
||||
|
||||
/* Extended header if present */
|
||||
if (work->hdr.flags & ID3V2_HDR_FLAG_EXTHDR) {
|
||||
work->hdr.ext_hdr_size = read_synch_uint (work->hdr.frame_data, 4);
|
||||
if (work->hdr.ext_hdr_size < 6 ||
|
||||
(work->hdr.ext_hdr_size) > work->hdr.frame_data_size) {
|
||||
GST_DEBUG ("Invalid extended header. Broken tag");
|
||||
return ID3TAGS_BROKEN_TAG;
|
||||
}
|
||||
work->hdr.ext_flag_bytes = work->hdr.frame_data[4];
|
||||
if (5 + work->hdr.ext_flag_bytes > work->hdr.frame_data_size) {
|
||||
GST_DEBUG
|
||||
("Tag claims extended header, but doesn't have enough bytes. Broken tag");
|
||||
return ID3TAGS_BROKEN_TAG;
|
||||
}
|
||||
|
||||
work->hdr.ext_flag_data = work->hdr.frame_data + 5;
|
||||
work->hdr.frame_data += work->hdr.ext_hdr_size;
|
||||
work->hdr.frame_data_size -= work->hdr.ext_hdr_size;
|
||||
}
|
||||
|
||||
start = GST_BUFFER_DATA (work->buffer);
|
||||
frame_hdr_size = id3demux_id3v2_frame_hdr_size (work->hdr.version);
|
||||
if (work->hdr.frame_data_size <= frame_hdr_size) {
|
||||
GST_DEBUG ("Tag has no data frames. Broken tag");
|
||||
return ID3TAGS_BROKEN_TAG; /* Must have at least one frame */
|
||||
}
|
||||
|
||||
work->tags = gst_tag_list_new ();
|
||||
g_return_val_if_fail (work->tags != NULL, ID3TAGS_READ_TAG);
|
||||
|
||||
while (work->hdr.frame_data_size > frame_hdr_size) {
|
||||
guint frame_size = 0;
|
||||
gchar frame_id[5] = "";
|
||||
guint16 frame_flags = 0x0;
|
||||
gboolean obsolete_id = FALSE;
|
||||
gboolean read_synch_size = TRUE;
|
||||
guint i;
|
||||
|
||||
/* Read the header */
|
||||
switch (ID3V2_VER_MAJOR (work->hdr.version)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
frame_id[0] = work->hdr.frame_data[0];
|
||||
frame_id[1] = work->hdr.frame_data[1];
|
||||
frame_id[2] = work->hdr.frame_data[2];
|
||||
frame_id[3] = 0;
|
||||
frame_id[4] = 0;
|
||||
obsolete_id = convert_fid_to_v240 (frame_id);
|
||||
|
||||
/* 3 byte non-synchsafe size */
|
||||
frame_size = work->hdr.frame_data[3] << 16 |
|
||||
work->hdr.frame_data[4] << 8 | work->hdr.frame_data[5];
|
||||
frame_flags = 0;
|
||||
break;
|
||||
case 3:
|
||||
read_synch_size = FALSE; /* 2.3 frame size is not synch-safe */
|
||||
case 4:
|
||||
default:
|
||||
frame_id[0] = work->hdr.frame_data[0];
|
||||
frame_id[1] = work->hdr.frame_data[1];
|
||||
frame_id[2] = work->hdr.frame_data[2];
|
||||
frame_id[3] = work->hdr.frame_data[3];
|
||||
frame_id[4] = 0;
|
||||
if (read_synch_size)
|
||||
frame_size = read_synch_uint (work->hdr.frame_data + 4, 4);
|
||||
else
|
||||
frame_size = GST_READ_UINT32_BE (work->hdr.frame_data + 4);
|
||||
|
||||
frame_flags = GST_READ_UINT16_BE (work->hdr.frame_data + 8);
|
||||
|
||||
if (ID3V2_VER_MAJOR (work->hdr.version) == 3) {
|
||||
frame_flags &= ID3V2_3_FRAME_FLAGS_MASK;
|
||||
obsolete_id = convert_fid_to_v240 (frame_id);
|
||||
if (obsolete_id)
|
||||
GST_DEBUG ("Ignoring v2.3 frame %s", frame_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
work->hdr.frame_data += frame_hdr_size;
|
||||
work->hdr.frame_data_size -= frame_hdr_size;
|
||||
|
||||
if (frame_size > work->hdr.frame_data_size || strcmp (frame_id, "") == 0)
|
||||
break; /* No more frames to read */
|
||||
|
||||
/* Sanitize frame id */
|
||||
switch (ID3V2_VER_MAJOR (work->hdr.version)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (!g_ascii_isalnum (frame_id[i]))
|
||||
frame_id[i] = '_';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!g_ascii_isalnum (frame_id[i]))
|
||||
frame_id[i] = '_';
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
GST_LOG
|
||||
("Frame @ %ld (0x%02lx) id %s size %u, next=%ld (0x%02lx) obsolete=%d",
|
||||
(glong) (work->hdr.frame_data - start),
|
||||
(glong) (work->hdr.frame_data - start), frame_id, frame_size,
|
||||
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
||||
(glong) (work->hdr.frame_data + frame_hdr_size + frame_size - start),
|
||||
obsolete_id);
|
||||
#define flag_string(flag,str) \
|
||||
((frame_flags & (flag)) ? (str) : "")
|
||||
GST_LOG ("Frame header flags: 0x%04x %s %s %s %s %s %s %s", frame_flags,
|
||||
flag_string (ID3V2_FRAME_STATUS_FRAME_ALTER_PRESERVE, "ALTER_PRESERVE"),
|
||||
flag_string (ID3V2_FRAME_STATUS_READONLY, "READONLY"),
|
||||
flag_string (ID3V2_FRAME_FORMAT_GROUPING_ID, "GROUPING_ID"),
|
||||
flag_string (ID3V2_FRAME_FORMAT_COMPRESSION, "COMPRESSION"),
|
||||
flag_string (ID3V2_FRAME_FORMAT_ENCRYPTION, "ENCRYPTION"),
|
||||
flag_string (ID3V2_FRAME_FORMAT_UNSYNCHRONISATION, "UNSYNC"),
|
||||
flag_string (ID3V2_FRAME_FORMAT_DATA_LENGTH_INDICATOR, "LENGTH_IND"));
|
||||
#undef flag_str
|
||||
#endif
|
||||
|
||||
if (!obsolete_id) {
|
||||
/* Now, read, decompress etc the contents of the frame
|
||||
* into a TagList entry */
|
||||
work->cur_frame_size = frame_size;
|
||||
work->frame_id = frame_id;
|
||||
work->frame_flags = frame_flags;
|
||||
|
||||
if (id3demux_id3v2_parse_frame (work)) {
|
||||
GST_LOG ("Extracted frame with id %s", frame_id);
|
||||
} else {
|
||||
GST_LOG ("Failed to extract frame with id %s", frame_id);
|
||||
id3demux_add_id3v2_frame_blob_to_taglist (work, frame_size);
|
||||
}
|
||||
}
|
||||
work->hdr.frame_data += frame_size;
|
||||
work->hdr.frame_data_size -= frame_size;
|
||||
}
|
||||
|
||||
if (gst_structure_n_fields (GST_STRUCTURE (work->tags)) == 0) {
|
||||
GST_DEBUG ("Could not extract any frames from tag. Broken or empty tag");
|
||||
gst_tag_list_free (work->tags);
|
||||
work->tags = NULL;
|
||||
return ID3TAGS_BROKEN_TAG;
|
||||
}
|
||||
|
||||
/* Set day/month now if they were in a separate (obsolete) TDAT frame */
|
||||
if (work->pending_day != 0 && work->pending_month != 0) {
|
||||
GDate *date = NULL;
|
||||
|
||||
if (gst_tag_list_get_date (work->tags, GST_TAG_DATE, &date)) {
|
||||
g_date_set_day (date, work->pending_day);
|
||||
g_date_set_month (date, work->pending_month);
|
||||
gst_tag_list_add (work->tags, GST_TAG_MERGE_REPLACE, GST_TAG_DATE,
|
||||
date, NULL);
|
||||
g_date_free (date);
|
||||
}
|
||||
}
|
||||
|
||||
return ID3TAGS_READ_TAG;
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/* Copyright 2005 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ID3TAGS_H__
|
||||
#define __ID3TAGS_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* private tag for storing unprocessed ID3v2 frames */
|
||||
#define GST_ID3_DEMUX_TAG_ID3V2_FRAME "private-id3v2-frame"
|
||||
|
||||
#define ID3V1_TAG_SIZE 128
|
||||
#define ID3V2_MARK_SIZE 3
|
||||
#define ID3V2_HDR_SIZE 10
|
||||
|
||||
typedef enum {
|
||||
ID3TAGS_MORE_DATA,
|
||||
ID3TAGS_READ_TAG,
|
||||
ID3TAGS_BROKEN_TAG
|
||||
} ID3TagsResult;
|
||||
|
||||
/* From id3tags.c */
|
||||
guint id3demux_calc_id3v2_tag_size (GstBuffer * buf);
|
||||
ID3TagsResult id3demux_read_id3v2_tag (GstBuffer *buffer, guint *id3v2_size,
|
||||
GstTagList **tags);
|
||||
|
||||
guint read_synch_uint (const guint8 * data, guint size);
|
||||
|
||||
/* Things shared by id3tags.c and id3v2frames.c */
|
||||
#define ID3V2_VERSION 0x0400
|
||||
#define ID3V2_VER_MAJOR(v) ((v) >> 8)
|
||||
#define ID3V2_VER_MINOR(v) ((v) & 0xff)
|
||||
|
||||
typedef struct {
|
||||
guint16 version;
|
||||
guint8 flags;
|
||||
guint32 size;
|
||||
|
||||
guint8 *frame_data;
|
||||
guint32 frame_data_size;
|
||||
|
||||
guint32 ext_hdr_size;
|
||||
guint8 ext_flag_bytes;
|
||||
guint8 *ext_flag_data;
|
||||
} ID3v2Header;
|
||||
|
||||
typedef struct {
|
||||
ID3v2Header hdr;
|
||||
|
||||
GstBuffer *buffer;
|
||||
GstTagList *tags;
|
||||
|
||||
/* Current frame decoding */
|
||||
guint cur_frame_size;
|
||||
gchar *frame_id;
|
||||
guint16 frame_flags;
|
||||
|
||||
guint8 *parse_data;
|
||||
guint parse_size;
|
||||
|
||||
/* To collect day/month from obsolete TDAT frame if it exists */
|
||||
guint pending_month;
|
||||
guint pending_day;
|
||||
} ID3TagsWorking;
|
||||
|
||||
enum {
|
||||
ID3V2_HDR_FLAG_UNSYNC = 0x80,
|
||||
ID3V2_HDR_FLAG_EXTHDR = 0x40,
|
||||
ID3V2_HDR_FLAG_EXPERIMENTAL = 0x20,
|
||||
ID3V2_HDR_FLAG_FOOTER = 0x10
|
||||
};
|
||||
|
||||
enum {
|
||||
ID3V2_EXT_FLAG_UPDATE = 0x80,
|
||||
ID3V2_EXT_FLAG_CRC = 0x40,
|
||||
ID3V2_EXT_FLAG_RESTRICTED = 0x20
|
||||
};
|
||||
|
||||
enum {
|
||||
ID3V2_FRAME_STATUS_FRAME_ALTER_PRESERVE = 0x4000,
|
||||
ID3V2_FRAME_STATUS_FILE_ALTER_PRESERVE = 0x2000,
|
||||
ID3V2_FRAME_STATUS_READONLY = 0x1000,
|
||||
ID3V2_FRAME_FORMAT_GROUPING_ID = 0x0040,
|
||||
ID3V2_FRAME_FORMAT_COMPRESSION = 0x0008,
|
||||
ID3V2_FRAME_FORMAT_ENCRYPTION = 0x0004,
|
||||
ID3V2_FRAME_FORMAT_UNSYNCHRONISATION = 0x0002,
|
||||
ID3V2_FRAME_FORMAT_DATA_LENGTH_INDICATOR = 0x0001
|
||||
};
|
||||
|
||||
#define ID3V2_3_FRAME_FLAGS_MASK \
|
||||
(ID3V2_FRAME_STATUS_FRAME_ALTER_PRESERVE | \
|
||||
ID3V2_FRAME_STATUS_FILE_ALTER_PRESERVE | \
|
||||
ID3V2_FRAME_STATUS_READONLY | \
|
||||
ID3V2_FRAME_FORMAT_GROUPING_ID | \
|
||||
ID3V2_FRAME_FORMAT_COMPRESSION | \
|
||||
ID3V2_FRAME_FORMAT_ENCRYPTION)
|
||||
|
||||
/* From id3v2frames.c */
|
||||
gboolean id3demux_id3v2_parse_frame (ID3TagsWorking *work);
|
||||
|
||||
guint8 * id3demux_ununsync_data (const guint8 * unsync_data, guint32 * size);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
@ -1,733 +0,0 @@
|
|||
|
||||
Informal standard M. Nilsson
|
||||
Document: id3v2.4.0-structure.txt 16 September 2001
|
||||
|
||||
|
||||
ID3 tag version 2.4.0 - Main Structure
|
||||
|
||||
Status of this document
|
||||
|
||||
This document is an informal standard and replaces the ID3v2.3.0
|
||||
standard [ID3v2]. A formal standard will use another revision number
|
||||
even if the content is identical to document. The contents in this
|
||||
document may change for clarifications but never for added or altered
|
||||
functionallity.
|
||||
|
||||
Distribution of this document is unlimited.
|
||||
|
||||
|
||||
Abstract
|
||||
|
||||
This document describes the main structure of ID3v2.4.0, which is a
|
||||
revised version of the ID3v2 informal standard [ID3v2] version
|
||||
2.3.0. The ID3v2 offers a flexible way of storing audio meta
|
||||
information within the audio file itself. The information may be
|
||||
technical information, such as equalisation curves, as well as
|
||||
title, performer, copyright etc.
|
||||
|
||||
ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order
|
||||
to allow for implementations to be revised as easily as possible.
|
||||
|
||||
|
||||
1. Table of contents
|
||||
|
||||
Status of this document
|
||||
Abstract
|
||||
1. Table of contents
|
||||
2. Conventions in this document
|
||||
2. Standard overview
|
||||
3. ID3v2 overview
|
||||
3.1. ID3v2 header
|
||||
3.2. ID3v2 extended header
|
||||
3.3. Padding
|
||||
3.4. ID3v2 footer
|
||||
4. ID3v2 frames overview
|
||||
4.1. Frame header flags
|
||||
4.1.1. Frame status flags
|
||||
4.1.2. Frame format flags
|
||||
5. Tag location
|
||||
6. Unsynchronisation
|
||||
6.1. The unsynchronisation scheme
|
||||
6.2. Synchsafe integers
|
||||
7. Copyright
|
||||
8. References
|
||||
9. Author's Address
|
||||
|
||||
|
||||
2. Conventions in this document
|
||||
|
||||
Text within "" is a text string exactly as it appears in a tag.
|
||||
Numbers preceded with $ are hexadecimal and numbers preceded with %
|
||||
are binary. $xx is used to indicate a byte with unknown content. %x
|
||||
is used to indicate a bit with unknown content. The most significant
|
||||
bit (MSB) of a byte is called 'bit 7' and the least significant bit
|
||||
(LSB) is called 'bit 0'.
|
||||
|
||||
A tag is the whole tag described in this document. A frame is a block
|
||||
of information in the tag. The tag consists of a header, frames and
|
||||
optional padding. A field is a piece of information; one value, a
|
||||
string etc. A numeric string is a string that consists of the
|
||||
characters "0123456789" only.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in RFC 2119 [KEYWORDS].
|
||||
|
||||
|
||||
3. ID3v2 overview
|
||||
|
||||
ID3v2 is a general tagging format for audio, which makes it possible
|
||||
to store meta data about the audio inside the audio file itself. The
|
||||
ID3 tag described in this document is mainly targeted at files
|
||||
encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III
|
||||
and MPEG-2.5, but may work with other types of encoded audio or as a
|
||||
stand alone format for audio meta data.
|
||||
|
||||
ID3v2 is designed to be as flexible and expandable as possible to
|
||||
meet new meta information needs that might arise. To achieve that
|
||||
ID3v2 is constructed as a container for several information blocks,
|
||||
called frames, whose format need not be known to the software that
|
||||
encounters them. At the start of every frame is an unique and
|
||||
predefined identifier, a size descriptor that allows software to skip
|
||||
unknown frames and a flags field. The flags describes encoding
|
||||
details and if the frame should remain in the tag, should it be
|
||||
unknown to the software, if the file is altered.
|
||||
|
||||
The bitorder in ID3v2 is most significant bit first (MSB). The
|
||||
byteorder in multibyte numbers is most significant byte first (e.g.
|
||||
$12345678 would be encoded $12 34 56 78), also known as big endian
|
||||
and network byte order.
|
||||
|
||||
Overall tag structure:
|
||||
|
||||
+-----------------------------+
|
||||
| Header (10 bytes) |
|
||||
+-----------------------------+
|
||||
| Extended Header |
|
||||
| (variable length, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
| Frames (variable length) |
|
||||
+-----------------------------+
|
||||
| Padding |
|
||||
| (variable length, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
| Footer (10 bytes, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
|
||||
In general, padding and footer are mutually exclusive. See details in
|
||||
sections 3.3, 3.4 and 5.
|
||||
|
||||
|
||||
3.1. ID3v2 header
|
||||
|
||||
The first part of the ID3v2 tag is the 10 byte tag header, laid out
|
||||
as follows:
|
||||
|
||||
ID3v2/file identifier "ID3"
|
||||
ID3v2 version $04 00
|
||||
ID3v2 flags %abcd0000
|
||||
ID3v2 size 4 * %0xxxxxxx
|
||||
|
||||
The first three bytes of the tag are always "ID3", to indicate that
|
||||
this is an ID3v2 tag, directly followed by the two version bytes. The
|
||||
first byte of ID3v2 version is its major version, while the second
|
||||
byte is its revision number. In this case this is ID3v2.4.0. All
|
||||
revisions are backwards compatible while major versions are not. If
|
||||
software with ID3v2.4.0 and below support should encounter version
|
||||
five or higher it should simply ignore the whole tag. Version or
|
||||
revision will never be $FF.
|
||||
|
||||
The version is followed by the ID3v2 flags field, of which currently
|
||||
four flags are used.
|
||||
|
||||
|
||||
a - Unsynchronisation
|
||||
|
||||
Bit 7 in the 'ID3v2 flags' indicates whether or not
|
||||
unsynchronisation is applied on all frames (see section 6.1 for
|
||||
details); a set bit indicates usage.
|
||||
|
||||
|
||||
b - Extended header
|
||||
|
||||
The second bit (bit 6) indicates whether or not the header is
|
||||
followed by an extended header. The extended header is described in
|
||||
section 3.2. A set bit indicates the presence of an extended
|
||||
header.
|
||||
|
||||
|
||||
c - Experimental indicator
|
||||
|
||||
The third bit (bit 5) is used as an 'experimental indicator'. This
|
||||
flag SHALL always be set when the tag is in an experimental stage.
|
||||
|
||||
|
||||
d - Footer present
|
||||
|
||||
Bit 4 indicates that a footer (section 3.4) is present at the very
|
||||
end of the tag. A set bit indicates the presence of a footer.
|
||||
|
||||
|
||||
All the other flags MUST be cleared. If one of these undefined flags
|
||||
are set, the tag might not be readable for a parser that does not
|
||||
know the flags function.
|
||||
|
||||
The ID3v2 tag size is stored as a 32 bit synchsafe integer (section
|
||||
6.2), making a total of 28 effective bits (representing up to 256MB).
|
||||
|
||||
The ID3v2 tag size is the sum of the byte length of the extended
|
||||
header, the padding and the frames after unsynchronisation. If a
|
||||
footer is present this equals to ('total size' - 20) bytes, otherwise
|
||||
('total size' - 10) bytes.
|
||||
|
||||
An ID3v2 tag can be detected with the following pattern:
|
||||
$49 44 33 yy yy xx zz zz zz zz
|
||||
Where yy is less than $FF, xx is the 'flags' byte and zz is less than
|
||||
$80.
|
||||
|
||||
|
||||
3.2. Extended header
|
||||
|
||||
The extended header contains information that can provide further
|
||||
insight in the structure of the tag, but is not vital to the correct
|
||||
parsing of the tag information; hence the extended header is
|
||||
optional.
|
||||
|
||||
Extended header size 4 * %0xxxxxxx
|
||||
Number of flag bytes $01
|
||||
Extended Flags $xx
|
||||
|
||||
Where the 'Extended header size' is the size of the whole extended
|
||||
header, stored as a 32 bit synchsafe integer. An extended header can
|
||||
thus never have a size of fewer than six bytes.
|
||||
|
||||
The extended flags field, with its size described by 'number of flag
|
||||
bytes', is defined as:
|
||||
|
||||
%0bcd0000
|
||||
|
||||
Each flag that is set in the extended header has data attached, which
|
||||
comes in the order in which the flags are encountered (i.e. the data
|
||||
for flag 'b' comes before the data for flag 'c'). Unset flags cannot
|
||||
have any attached data. All unknown flags MUST be unset and their
|
||||
corresponding data removed when a tag is modified.
|
||||
|
||||
Every set flag's data starts with a length byte, which contains a
|
||||
value between 0 and 127 ($00 - $7f), followed by data that has the
|
||||
field length indicated by the length byte. If a flag has no attached
|
||||
data, the value $00 is used as length byte.
|
||||
|
||||
|
||||
b - Tag is an update
|
||||
|
||||
If this flag is set, the present tag is an update of a tag found
|
||||
earlier in the present file or stream. If frames defined as unique
|
||||
are found in the present tag, they are to override any
|
||||
corresponding ones found in the earlier tag. This flag has no
|
||||
corresponding data.
|
||||
|
||||
Flag data length $00
|
||||
|
||||
c - CRC data present
|
||||
|
||||
If this flag is set, a CRC-32 [ISO-3309] data is included in the
|
||||
extended header. The CRC is calculated on all the data between the
|
||||
header and footer as indicated by the header's tag length field,
|
||||
minus the extended header. Note that this includes the padding (if
|
||||
there is any), but excludes the footer. The CRC-32 is stored as an
|
||||
35 bit synchsafe integer, leaving the upper four bits always
|
||||
zeroed.
|
||||
|
||||
Flag data length $05
|
||||
Total frame CRC 5 * %0xxxxxxx
|
||||
|
||||
d - Tag restrictions
|
||||
|
||||
For some applications it might be desired to restrict a tag in more
|
||||
ways than imposed by the ID3v2 specification. Note that the
|
||||
presence of these restrictions does not affect how the tag is
|
||||
decoded, merely how it was restricted before encoding. If this flag
|
||||
is set the tag is restricted as follows:
|
||||
|
||||
Flag data length $01
|
||||
Restrictions %ppqrrstt
|
||||
|
||||
p - Tag size restrictions
|
||||
|
||||
00 No more than 128 frames and 1 MB total tag size.
|
||||
01 No more than 64 frames and 128 KB total tag size.
|
||||
10 No more than 32 frames and 40 KB total tag size.
|
||||
11 No more than 32 frames and 4 KB total tag size.
|
||||
|
||||
q - Text encoding restrictions
|
||||
|
||||
0 No restrictions
|
||||
1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or
|
||||
UTF-8 [UTF-8].
|
||||
|
||||
r - Text fields size restrictions
|
||||
|
||||
00 No restrictions
|
||||
01 No string is longer than 1024 characters.
|
||||
10 No string is longer than 128 characters.
|
||||
11 No string is longer than 30 characters.
|
||||
|
||||
Note that nothing is said about how many bytes is used to
|
||||
represent those characters, since it is encoding dependent. If a
|
||||
text frame consists of more than one string, the sum of the
|
||||
strungs is restricted as stated.
|
||||
|
||||
s - Image encoding restrictions
|
||||
|
||||
0 No restrictions
|
||||
1 Images are encoded only with PNG [PNG] or JPEG [JFIF].
|
||||
|
||||
t - Image size restrictions
|
||||
|
||||
00 No restrictions
|
||||
01 All images are 256x256 pixels or smaller.
|
||||
10 All images are 64x64 pixels or smaller.
|
||||
11 All images are exactly 64x64 pixels, unless required
|
||||
otherwise.
|
||||
|
||||
|
||||
3.3. Padding
|
||||
|
||||
It is OPTIONAL to include padding after the final frame (at the end
|
||||
of the ID3 tag), making the size of all the frames together smaller
|
||||
than the size given in the tag header. A possible purpose of this
|
||||
padding is to allow for adding a few additional frames or enlarge
|
||||
existing frames within the tag without having to rewrite the entire
|
||||
file. The value of the padding bytes must be $00. A tag MUST NOT have
|
||||
any padding between the frames or between the tag header and the
|
||||
frames. Furthermore it MUST NOT have any padding when a tag footer is
|
||||
added to the tag.
|
||||
|
||||
|
||||
3.4. ID3v2 footer
|
||||
|
||||
To speed up the process of locating an ID3v2 tag when searching from
|
||||
the end of a file, a footer can be added to the tag. It is REQUIRED
|
||||
to add a footer to an appended tag, i.e. a tag located after all
|
||||
audio data. The footer is a copy of the header, but with a different
|
||||
identifier.
|
||||
|
||||
ID3v2 identifier "3DI"
|
||||
ID3v2 version $04 00
|
||||
ID3v2 flags %abcd0000
|
||||
ID3v2 size 4 * %0xxxxxxx
|
||||
|
||||
|
||||
4. ID3v2 frame overview
|
||||
|
||||
All ID3v2 frames consists of one frame header followed by one or more
|
||||
fields containing the actual information. The header is always 10
|
||||
bytes and laid out as follows:
|
||||
|
||||
Frame ID $xx xx xx xx (four characters)
|
||||
Size 4 * %0xxxxxxx
|
||||
Flags $xx xx
|
||||
|
||||
The frame ID is made out of the characters capital A-Z and 0-9.
|
||||
Identifiers beginning with "X", "Y" and "Z" are for experimental
|
||||
frames and free for everyone to use, without the need to set the
|
||||
experimental bit in the tag header. Bear in mind that someone else
|
||||
might have used the same identifier as you. All other identifiers are
|
||||
either used or reserved for future use.
|
||||
|
||||
The frame ID is followed by a size descriptor containing the size of
|
||||
the data in the final frame, after encryption, compression and
|
||||
unsynchronisation. The size is excluding the frame header ('total
|
||||
frame size' - 10 bytes) and stored as a 32 bit synchsafe integer.
|
||||
|
||||
In the frame header the size descriptor is followed by two flag
|
||||
bytes. These flags are described in section 4.1.
|
||||
|
||||
There is no fixed order of the frames' appearance in the tag,
|
||||
although it is desired that the frames are arranged in order of
|
||||
significance concerning the recognition of the file. An example of
|
||||
such order: UFID, TIT2, MCDI, TRCK ...
|
||||
|
||||
A tag MUST contain at least one frame. A frame must be at least 1
|
||||
byte big, excluding the header.
|
||||
|
||||
If nothing else is said, strings, including numeric strings and URLs
|
||||
[URL], are represented as ISO-8859-1 [ISO-8859-1] characters in the
|
||||
range $20 - $FF. Such strings are represented in frame descriptions
|
||||
as <text string>, or <full text string> if newlines are allowed. If
|
||||
nothing else is said newline character is forbidden. In ISO-8859-1 a
|
||||
newline is represented, when allowed, with $0A only.
|
||||
|
||||
Frames that allow different types of text encoding contains a text
|
||||
encoding description byte. Possible encodings:
|
||||
|
||||
$00 ISO-8859-1 [ISO-8859-1]. Terminated with $00.
|
||||
$01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
|
||||
strings in the same frame SHALL have the same byteorder.
|
||||
Terminated with $00 00.
|
||||
$02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
|
||||
Terminated with $00 00.
|
||||
$03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
|
||||
|
||||
Strings dependent on encoding are represented in frame descriptions
|
||||
as <text string according to encoding>, or <full text string
|
||||
according to encoding> if newlines are allowed. Any empty strings of
|
||||
type $01 which are NULL-terminated may have the Unicode BOM followed
|
||||
by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00).
|
||||
|
||||
The timestamp fields are based on a subset of ISO 8601. When being as
|
||||
precise as possible the format of a time string is
|
||||
yyyy-MM-ddTHH:mm:ss (year, "-", month, "-", day, "T", hour (out of
|
||||
24), ":", minutes, ":", seconds), but the precision may be reduced by
|
||||
removing as many time indicators as wanted. Hence valid timestamps
|
||||
are
|
||||
yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and
|
||||
yyyy-MM-ddTHH:mm:ss. All time stamps are UTC. For durations, use
|
||||
the slash character as described in 8601, and for multiple non-
|
||||
contiguous dates, use multiple strings, if allowed by the frame
|
||||
definition.
|
||||
|
||||
The three byte language field, present in several frames, is used to
|
||||
describe the language of the frame's content, according to ISO-639-2
|
||||
[ISO-639-2]. The language should be represented in lower case. If the
|
||||
language is not known the string "XXX" should be used.
|
||||
|
||||
All URLs [URL] MAY be relative, e.g. "picture.png", "../doc.txt".
|
||||
|
||||
If a frame is longer than it should be, e.g. having more fields than
|
||||
specified in this document, that indicates that additions to the
|
||||
frame have been made in a later version of the ID3v2 standard. This
|
||||
is reflected by the revision number in the header of the tag.
|
||||
|
||||
|
||||
4.1. Frame header flags
|
||||
|
||||
In the frame header the size descriptor is followed by two flag
|
||||
bytes. All unused flags MUST be cleared. The first byte is for
|
||||
'status messages' and the second byte is a format description. If an
|
||||
unknown flag is set in the first byte the frame MUST NOT be changed
|
||||
without that bit cleared. If an unknown flag is set in the second
|
||||
byte the frame is likely to not be readable. Some flags in the second
|
||||
byte indicates that extra information is added to the header. These
|
||||
fields of extra information is ordered as the flags that indicates
|
||||
them. The flags field is defined as follows (l and o left out because
|
||||
ther resemblence to one and zero):
|
||||
|
||||
%0abc0000 %0h00kmnp
|
||||
|
||||
Some frame format flags indicate that additional information fields
|
||||
are added to the frame. This information is added after the frame
|
||||
header and before the frame data in the same order as the flags that
|
||||
indicates them. I.e. the four bytes of decompressed size will precede
|
||||
the encryption method byte. These additions affects the 'frame size'
|
||||
field, but are not subject to encryption or compression.
|
||||
|
||||
The default status flags setting for a frame is, unless stated
|
||||
otherwise, 'preserved if tag is altered' and 'preserved if file is
|
||||
altered', i.e. %00000000.
|
||||
|
||||
|
||||
4.1.1. Frame status flags
|
||||
|
||||
a - Tag alter preservation
|
||||
|
||||
This flag tells the tag parser what to do with this frame if it is
|
||||
unknown and the tag is altered in any way. This applies to all
|
||||
kinds of alterations, including adding more padding and reordering
|
||||
the frames.
|
||||
|
||||
0 Frame should be preserved.
|
||||
1 Frame should be discarded.
|
||||
|
||||
|
||||
b - File alter preservation
|
||||
|
||||
This flag tells the tag parser what to do with this frame if it is
|
||||
unknown and the file, excluding the tag, is altered. This does not
|
||||
apply when the audio is completely replaced with other audio data.
|
||||
|
||||
0 Frame should be preserved.
|
||||
1 Frame should be discarded.
|
||||
|
||||
|
||||
c - Read only
|
||||
|
||||
This flag, if set, tells the software that the contents of this
|
||||
frame are intended to be read only. Changing the contents might
|
||||
break something, e.g. a signature. If the contents are changed,
|
||||
without knowledge of why the frame was flagged read only and
|
||||
without taking the proper means to compensate, e.g. recalculating
|
||||
the signature, the bit MUST be cleared.
|
||||
|
||||
|
||||
4.1.2. Frame format flags
|
||||
|
||||
h - Grouping identity
|
||||
|
||||
This flag indicates whether or not this frame belongs in a group
|
||||
with other frames. If set, a group identifier byte is added to the
|
||||
frame. Every frame with the same group identifier belongs to the
|
||||
same group.
|
||||
|
||||
0 Frame does not contain group information
|
||||
1 Frame contains group information
|
||||
|
||||
|
||||
k - Compression
|
||||
|
||||
This flag indicates whether or not the frame is compressed.
|
||||
A 'Data Length Indicator' byte MUST be included in the frame.
|
||||
|
||||
0 Frame is not compressed.
|
||||
1 Frame is compressed using zlib [zlib] deflate method.
|
||||
If set, this requires the 'Data Length Indicator' bit
|
||||
to be set as well.
|
||||
|
||||
|
||||
m - Encryption
|
||||
|
||||
This flag indicates whether or not the frame is encrypted. If set,
|
||||
one byte indicating with which method it was encrypted will be
|
||||
added to the frame. See description of the ENCR frame for more
|
||||
information about encryption method registration. Encryption
|
||||
should be done after compression. Whether or not setting this flag
|
||||
requires the presence of a 'Data Length Indicator' depends on the
|
||||
specific algorithm used.
|
||||
|
||||
0 Frame is not encrypted.
|
||||
1 Frame is encrypted.
|
||||
|
||||
n - Unsynchronisation
|
||||
|
||||
This flag indicates whether or not unsynchronisation was applied
|
||||
to this frame. See section 6 for details on unsynchronisation.
|
||||
If this flag is set all data from the end of this header to the
|
||||
end of this frame has been unsynchronised. Although desirable, the
|
||||
presence of a 'Data Length Indicator' is not made mandatory by
|
||||
unsynchronisation.
|
||||
|
||||
0 Frame has not been unsynchronised.
|
||||
1 Frame has been unsyrchronised.
|
||||
|
||||
p - Data length indicator
|
||||
|
||||
This flag indicates that a data length indicator has been added to
|
||||
the frame. The data length indicator is the value one would write
|
||||
as the 'Frame length' if all of the frame format flags were
|
||||
zeroed, represented as a 32 bit synchsafe integer.
|
||||
|
||||
0 There is no Data Length Indicator.
|
||||
1 A data length Indicator has been added to the frame.
|
||||
|
||||
|
||||
5. Tag location
|
||||
|
||||
The default location of an ID3v2 tag is prepended to the audio so
|
||||
that players can benefit from the information when the data is
|
||||
streamed. It is however possible to append the tag, or make a
|
||||
prepend/append combination. When deciding upon where an unembedded
|
||||
tag should be located, the following order of preference SHOULD be
|
||||
considered.
|
||||
|
||||
1. Prepend the tag.
|
||||
|
||||
2. Prepend a tag with all vital information and add a second tag at
|
||||
the end of the file, before tags from other tagging systems. The
|
||||
first tag is required to have a SEEK frame.
|
||||
|
||||
3. Add a tag at the end of the file, before tags from other tagging
|
||||
systems.
|
||||
|
||||
In case 2 and 3 the tag can simply be appended if no other known tags
|
||||
are present. The suggested method to find ID3v2 tags are:
|
||||
|
||||
1. Look for a prepended tag using the pattern found in section 3.1.
|
||||
|
||||
2. If a SEEK frame was found, use its values to guide further
|
||||
searching.
|
||||
|
||||
3. Look for a tag footer, scanning from the back of the file.
|
||||
|
||||
For every new tag that is found, the old tag should be discarded
|
||||
unless the update flag in the extended header (section 3.2) is set.
|
||||
|
||||
|
||||
6. Unsynchronisation
|
||||
|
||||
The only purpose of unsynchronisation is to make the ID3v2 tag as
|
||||
compatible as possible with existing software and hardware. There is
|
||||
no use in 'unsynchronising' tags if the file is only to be processed
|
||||
only by ID3v2 aware software and hardware. Unsynchronisation is only
|
||||
useful with tags in MPEG 1/2 layer I, II and III, MPEG 2.5 and AAC
|
||||
files.
|
||||
|
||||
|
||||
6.1. The unsynchronisation scheme
|
||||
|
||||
Whenever a false synchronisation is found within the tag, one zeroed
|
||||
byte is inserted after the first false synchronisation byte. The
|
||||
format of synchronisations that should be altered by ID3 encoders is
|
||||
as follows:
|
||||
|
||||
%11111111 111xxxxx
|
||||
|
||||
and should be replaced with:
|
||||
|
||||
%11111111 00000000 111xxxxx
|
||||
|
||||
This has the side effect that all $FF 00 combinations have to be
|
||||
altered, so they will not be affected by the decoding process.
|
||||
Therefore all the $FF 00 combinations have to be replaced with the
|
||||
$FF 00 00 combination during the unsynchronisation.
|
||||
|
||||
To indicate usage of the unsynchronisation, the unsynchronisation
|
||||
flag in the frame header should be set. This bit MUST be set if the
|
||||
frame was altered by the unsynchronisation and SHOULD NOT be set if
|
||||
unaltered. If all frames in the tag are unsynchronised the
|
||||
unsynchronisation flag in the tag header SHOULD be set. It MUST NOT
|
||||
be set if the tag has a frame which is not unsynchronised.
|
||||
|
||||
Assume the first byte of the audio to be $FF. The special case when
|
||||
the last byte of the last frame is $FF and no padding nor footer is
|
||||
used will then introduce a false synchronisation. This can be solved
|
||||
by adding a footer, adding padding or unsynchronising the frame and
|
||||
add $00 to the end of the frame data, thus adding more byte to the
|
||||
frame size than a normal unsynchronisation would. Although not
|
||||
preferred, it is allowed to apply the last method on all frames
|
||||
ending with $FF.
|
||||
|
||||
It is preferred that the tag is either completely unsynchronised or
|
||||
not unsynchronised at all. A completely unsynchronised tag has no
|
||||
false synchonisations in it, as defined above, and does not end with
|
||||
$FF. A completely non-unsynchronised tag contains no unsynchronised
|
||||
frames, and thus the unsynchronisation flag in the header is cleared.
|
||||
|
||||
Do bear in mind, that if compression or encryption is used, the
|
||||
unsynchronisation scheme MUST be applied afterwards. When decoding an
|
||||
unsynchronised frame, the unsynchronisation scheme MUST be reversed
|
||||
first, encryption and decompression afterwards.
|
||||
|
||||
|
||||
6.2. Synchsafe integers
|
||||
|
||||
In some parts of the tag it is inconvenient to use the
|
||||
unsychronisation scheme because the size of unsynchronised data is
|
||||
not known in advance, which is particularly problematic with size
|
||||
descriptors. The solution in ID3v2 is to use synchsafe integers, in
|
||||
which there can never be any false synchs. Synchsafe integers are
|
||||
integers that keep its highest bit (bit 7) zeroed, making seven bits
|
||||
out of eight available. Thus a 32 bit synchsafe integer can store 28
|
||||
bits of information.
|
||||
|
||||
Example:
|
||||
|
||||
255 (%11111111) encoded as a 16 bit synchsafe integer is 383
|
||||
(%00000001 01111111).
|
||||
|
||||
|
||||
7. Copyright
|
||||
|
||||
Copyright (C) Martin Nilsson 2000. All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published
|
||||
and distributed, in whole or in part, without restriction of any
|
||||
kind, provided that a reference to this document is included on all
|
||||
such copies and derivative works. However, this document itself may
|
||||
not be modified in any way and reissued as the original document.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
'AS IS' basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
|
||||
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
8. References
|
||||
|
||||
[ID3v2] Martin Nilsson, 'ID3v2 informal standard'.
|
||||
|
||||
<url:http://www.id3.org/id3v2.3.0.txt>
|
||||
|
||||
[ISO-639-2] ISO/FDIS 639-2.
|
||||
'Codes for the representation of names of languages, Part 2: Alpha-3
|
||||
code.' Technical committee / subcommittee: TC 37 / SC 2
|
||||
|
||||
[ISO-3309] ISO 3309
|
||||
'Information Processing Systems--Data Communication High-Level Data
|
||||
Link Control Procedure--Frame Structure', IS 3309, October 1984, 3rd
|
||||
Edition.
|
||||
|
||||
[ISO-8859-1] ISO/IEC DIS 8859-1.
|
||||
'8-bit single-byte coded graphic character sets, Part 1: Latin
|
||||
alphabet No. 1.' Technical committee / subcommittee: JTC 1 / SC 2
|
||||
|
||||
[JFIF] 'JPEG File Interchange Format, version 1.02'
|
||||
|
||||
<url:http://www.w3.org/Graphics/JPEG/jfif.txt>
|
||||
|
||||
[KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate
|
||||
Requirement Levels', RFC 2119, March 1997.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2119.txt>
|
||||
|
||||
[MPEG] ISO/IEC 11172-3:1993.
|
||||
'Coding of moving pictures and associated audio for digital storage
|
||||
media at up to about 1,5 Mbit/s, Part 3: Audio.'
|
||||
Technical committee / subcommittee: JTC 1 / SC 29
|
||||
and
|
||||
ISO/IEC 13818-3:1995
|
||||
'Generic coding of moving pictures and associated audio information,
|
||||
Part 3: Audio.'
|
||||
Technical committee / subcommittee: JTC 1 / SC 29
|
||||
and
|
||||
ISO/IEC DIS 13818-3
|
||||
'Generic coding of moving pictures and associated audio information,
|
||||
Part 3: Audio (Revision of ISO/IEC 13818-3:1995)'
|
||||
|
||||
[PNG] 'Portable Network Graphics, version 1.0'
|
||||
|
||||
<url:http://www.w3.org/TR/REC-png-multi.html>
|
||||
|
||||
[UNICODE] The Unicode Consortium,
|
||||
'The Unicode Standard Version 3.0', ISBN 0-201-61633-5.
|
||||
|
||||
<url:http://www.unicode.org/unicode/standard/versions/Unicode3.0.htm>
|
||||
|
||||
[URL] T. Berners-Lee, L. Masinter & M. McCahill, 'Uniform Resource
|
||||
Locators (URL)', RFC 1738, December 1994.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc1738.txt>
|
||||
|
||||
[UTF-8] F. Yergeau, 'UTF-8, a transformation format of ISO 10646',
|
||||
RFC 2279, January 1998.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2279.txt>
|
||||
|
||||
[UTF-16] F. Yergeau, 'UTF-16, an encoding of ISO 10646', RFC 2781,
|
||||
February 2000.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2781.txt>
|
||||
|
||||
[ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, 'ZLIB
|
||||
Compressed Data Format Specification version 3.3', RFC 1950,
|
||||
May 1996.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc1950.txt>
|
||||
|
||||
|
||||
9. Author's Address
|
||||
|
||||
Written by
|
||||
|
||||
Martin Nilsson
|
||||
Rydsvägen 246 C. 30
|
||||
SE-584 34 Linköping
|
||||
Sweden
|
||||
|
||||
Email: nilsson@id3.org
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -5255,7 +5255,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
|||
/* sync sample atom */
|
||||
stream->stps_present = FALSE;
|
||||
if ((stream->stss_present =
|
||||
! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
|
||||
!!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
|
||||
&stream->stss) ? TRUE : FALSE) == TRUE) {
|
||||
/* copy atom data into a new buffer for later use */
|
||||
stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
|
||||
|
@ -5273,7 +5273,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
|||
|
||||
/* partial sync sample atom */
|
||||
if ((stream->stps_present =
|
||||
! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
|
||||
!!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
|
||||
&stream->stps) ? TRUE : FALSE) == TRUE) {
|
||||
/* copy atom data into a new buffer for later use */
|
||||
stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
|
||||
|
@ -5392,7 +5392,7 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
|
|||
|
||||
/* composition time-to-sample */
|
||||
if ((stream->ctts_present =
|
||||
! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
|
||||
!!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
|
||||
&stream->ctts) ? TRUE : FALSE) == TRUE) {
|
||||
/* copy atom data into a new buffer for later use */
|
||||
stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
|
||||
|
@ -7490,6 +7490,7 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
|
|||
case FOURCC_soun:
|
||||
case FOURCC_vide:
|
||||
/* retrieve bitrate, prefer avg then max */
|
||||
bitrate = 0;
|
||||
if (qtdemux->streams[i]->pending_tags) {
|
||||
gst_tag_list_get_uint (qtdemux->streams[i]->pending_tags,
|
||||
GST_TAG_MAXIMUM_BITRATE, &bitrate);
|
||||
|
|
|
@ -4947,7 +4947,7 @@ static GstRTSPResult
|
|||
gst_rtspsrc_setup_streams (GstRTSPSrc * src, gboolean async)
|
||||
{
|
||||
GList *walk;
|
||||
GstRTSPResult res;
|
||||
GstRTSPResult res = GST_RTSP_ERROR;
|
||||
GstRTSPMessage request = { 0 };
|
||||
GstRTSPMessage response = { 0 };
|
||||
GstRTSPStream *stream = NULL;
|
||||
|
@ -4979,6 +4979,9 @@ gst_rtspsrc_setup_streams (GstRTSPSrc * src, gboolean async)
|
|||
src->next_port_num = src->client_port_range.min;
|
||||
rtpport = rtcpport = 0;
|
||||
|
||||
if (G_UNLIKELY (src->streams == NULL))
|
||||
goto no_streams;
|
||||
|
||||
for (walk = src->streams; walk; walk = g_list_next (walk)) {
|
||||
GstRTSPConnection *conn;
|
||||
gchar *transports;
|
||||
|
@ -5231,6 +5234,12 @@ no_protocols:
|
|||
("Could not connect to server, no protocols left"));
|
||||
return GST_RTSP_ERROR;
|
||||
}
|
||||
no_streams:
|
||||
{
|
||||
GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL),
|
||||
("SDP contains no streams"));
|
||||
return GST_RTSP_ERROR;
|
||||
}
|
||||
create_request_failed:
|
||||
{
|
||||
gchar *str = gst_rtsp_strresult (res);
|
||||
|
|
|
@ -2001,9 +2001,10 @@ static gboolean
|
|||
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
||||
guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
|
||||
{
|
||||
struct v4l2_format fmt;
|
||||
struct v4l2_format fmt, prevfmt;
|
||||
int fd;
|
||||
int r;
|
||||
int prevfmt_valid;
|
||||
|
||||
g_return_val_if_fail (width != NULL, FALSE);
|
||||
g_return_val_if_fail (height != NULL, FALSE);
|
||||
|
@ -2014,6 +2015,11 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
|||
|
||||
fd = v4l2object->video_fd;
|
||||
|
||||
/* Some drivers are buggy and will modify the currently set format
|
||||
when processing VIDIOC_TRY_FMT, so we remember what is set at the
|
||||
minute, and will reset it when done. */
|
||||
prevfmt_valid = (v4l2_ioctl (fd, VIDIOC_G_FMT, &prevfmt) >= 0);
|
||||
|
||||
/* get size delimiters */
|
||||
memset (&fmt, 0, sizeof (fmt));
|
||||
fmt.type = v4l2object->type;
|
||||
|
@ -2036,12 +2042,12 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
|||
/* The driver might not implement TRY_FMT, in which case we will try
|
||||
S_FMT to probe */
|
||||
if (errno != ENOTTY)
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
/* Only try S_FMT if we're not actively capturing yet, which we shouldn't
|
||||
be, because we're still probing */
|
||||
if (GST_V4L2_IS_ACTIVE (v4l2object))
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
GST_LOG_OBJECT (v4l2object->element,
|
||||
"Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
|
||||
|
@ -2060,7 +2066,7 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
|||
}
|
||||
|
||||
if (r < 0)
|
||||
return FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (v4l2object->element,
|
||||
|
@ -2083,10 +2089,17 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
|||
GST_WARNING_OBJECT (v4l2object->element,
|
||||
"Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
|
||||
GST_FOURCC_ARGS (pixelformat), *width, *height);
|
||||
return FALSE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (prevfmt_valid)
|
||||
v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
if (prevfmt_valid)
|
||||
v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -99,6 +99,7 @@ gst_ximage_src_return_buf (GstXImageSrc * ximagesrc, GstBuffer * ximage)
|
|||
/* need to increment the refcount again to recycle */
|
||||
gst_buffer_ref (ximage);
|
||||
g_mutex_lock (ximagesrc->pool_lock);
|
||||
GST_BUFFER_FLAGS (GST_BUFFER (ximage)) = 0; /* clear out any flags from the previous use */
|
||||
ximagesrc->buffer_pool = g_slist_prepend (ximagesrc->buffer_pool, ximage);
|
||||
g_mutex_unlock (ximagesrc->pool_lock);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue