mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
Add avi subtitle element for bug #442034. Need seeking support and more support for character conversion.
Original commit message from CVS: * gst/avi/Makefile.am: * gst/avi/gstavi.c: * gst/avi/gstavisubtitle.c: * gst/avi/gstavisubtitle.h: * tests/check/Makefile.am: * tests/check/elements/avisubtitle.c: * win32/common/config.h: Add avi subtitle element for bug #442034. Need seeking support and more support for character conversion.
This commit is contained in:
parent
de9a28056e
commit
d0c62e9108
8 changed files with 517 additions and 7 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2007-12-18 Thijs Vermeir <thijsvermeir@gmail.com>
|
||||||
|
|
||||||
|
* gst/avi/Makefile.am:
|
||||||
|
* gst/avi/gstavi.c:
|
||||||
|
* gst/avi/gstavisubtitle.c:
|
||||||
|
* gst/avi/gstavisubtitle.h:
|
||||||
|
* tests/check/Makefile.am:
|
||||||
|
* tests/check/elements/avisubtitle.c:
|
||||||
|
* win32/common/config.h:
|
||||||
|
Add avi subtitle element for bug #442034. Need seeking support
|
||||||
|
and more support for character conversion.
|
||||||
|
|
||||||
2007-12-18 Tim-Philipp Müller <tim at centricular dot net>
|
2007-12-18 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* Makefile.am:
|
* Makefile.am:
|
||||||
|
|
|
@ -3,12 +3,14 @@ plugin_LTLIBRARIES = libgstavi.la
|
||||||
libgstavi_la_SOURCES = \
|
libgstavi_la_SOURCES = \
|
||||||
gstavi.c \
|
gstavi.c \
|
||||||
gstavimux.c \
|
gstavimux.c \
|
||||||
gstavidemux.c
|
gstavidemux.c \
|
||||||
|
gstavisubtitle.c
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
avi-ids.h \
|
avi-ids.h \
|
||||||
gstavimux.h \
|
gstavimux.h \
|
||||||
gstavidemux.h
|
gstavidemux.h \
|
||||||
|
gstavisubtitle.h
|
||||||
|
|
||||||
libgstavi_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
|
libgstavi_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
|
||||||
-I$(top_srcdir)/gst-libs
|
-I$(top_srcdir)/gst-libs
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "gstavidemux.h"
|
#include "gstavidemux.h"
|
||||||
#include "gstavimux.h"
|
#include "gstavimux.h"
|
||||||
|
#include "gstavisubtitle.h"
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
plugin_init (GstPlugin * plugin)
|
plugin_init (GstPlugin * plugin)
|
||||||
|
@ -41,7 +42,9 @@ plugin_init (GstPlugin * plugin)
|
||||||
if (!gst_element_register (plugin, "avidemux", GST_RANK_PRIMARY,
|
if (!gst_element_register (plugin, "avidemux", GST_RANK_PRIMARY,
|
||||||
GST_TYPE_AVI_DEMUX) ||
|
GST_TYPE_AVI_DEMUX) ||
|
||||||
!gst_element_register (plugin, "avimux", GST_RANK_NONE,
|
!gst_element_register (plugin, "avimux", GST_RANK_NONE,
|
||||||
GST_TYPE_AVI_MUX)) {
|
GST_TYPE_AVI_MUX) ||
|
||||||
|
!gst_element_register (plugin, "avisubtitle", GST_RANK_NONE,
|
||||||
|
GST_TYPE_AVI_SUBTITLE)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
207
gst/avi/gstavisubtitle.c
Normal file
207
gst/avi/gstavisubtitle.c
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <2007> Thijs Vermeir <thijsvermeir@gmail.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* example of a subtitle chunk in an avi file
|
||||||
|
* 00000000 (0x8051700): 47 41 42 32 00 02 00 10 00 00 00 45 00 6e 00 67 GAB2.......E.n.g
|
||||||
|
* 00000010 (0x8051710): 00 6c 00 69 00 73 00 68 00 00 00 04 00 8e 00 00 .l.i.s.h........
|
||||||
|
* 00000020 (0x8051720): 00 ef bb bf 31 0d 0a 30 30 3a 30 30 3a 30 30 2c ....1..00:00:00,
|
||||||
|
* 00000030 (0x8051730): 31 30 30 20 2d 2d 3e 20 30 30 3a 30 30 3a 30 32 100 --> 00:00:02
|
||||||
|
* 00000040 (0x8051740): 2c 30 30 30 0d 0a 3c 62 3e 41 6e 20 55 54 46 38 ,000..<b>An UTF8
|
||||||
|
* 00000050 (0x8051750): 20 53 75 62 74 69 74 6c 65 20 77 69 74 68 20 42 Subtitle with B
|
||||||
|
* 00000060 (0x8051760): 4f 4d 3c 2f 62 3e 0d 0a 0d 0a 32 0d 0a 30 30 3a OM</b>....2..00:
|
||||||
|
* 00000070 (0x8051770): 30 30 3a 30 32 2c 31 30 30 20 2d 2d 3e 20 30 30 00:02,100 --> 00
|
||||||
|
* 00000080 (0x8051780): 3a 30 30 3a 30 34 2c 30 30 30 0d 0a 53 6f 6d 65 :00:04,000..Some
|
||||||
|
* 00000090 (0x8051790): 74 68 69 6e 67 20 6e 6f 6e 41 53 43 49 49 20 2d thing nonASCII -
|
||||||
|
* 000000a0 (0x80517a0): 20 c2 b5 c3 b6 c3 a4 c3 bc c3 9f 0d 0a 0d 0a ..............
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gstavisubtitle.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (avisubtitle_debug);
|
||||||
|
#define GST_CAT_DEFAULT avisubtitle_debug
|
||||||
|
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_EVENT);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-subtitle-avi")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-subtitle")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstFlowReturn gst_avi_subtitle_chain (GstPad * pad, GstBuffer * buffer);
|
||||||
|
|
||||||
|
GST_BOILERPLATE (GstAviSubtitle, gst_avi_subtitle, GstElement,
|
||||||
|
GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
gst_avi_subtitle_utf8_file (GstBuffer * buffer, guint offset)
|
||||||
|
{
|
||||||
|
guint8 *file = GST_BUFFER_DATA (buffer) + offset;
|
||||||
|
|
||||||
|
if (file[0] == 0xEF && file[1] == 0xBB && file[2] == 0xBF) {
|
||||||
|
/* UTF-8 */
|
||||||
|
return gst_buffer_create_sub (buffer, offset + 3,
|
||||||
|
GST_BUFFER_SIZE (buffer) - offset - 3);
|
||||||
|
}
|
||||||
|
/* TODO Check for:
|
||||||
|
* 00 00 FE FF UTF-32, big-endian
|
||||||
|
* FF FE 00 00 UTF-32, little-endian
|
||||||
|
* FE FF UTF-16, big-endian
|
||||||
|
* FF FE UTF-16, little-endian
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* No BOM detected assuming UTF-8 */
|
||||||
|
return gst_buffer_create_sub (buffer, offset,
|
||||||
|
GST_BUFFER_SIZE (buffer) - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_avi_subtitle_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
{
|
||||||
|
guint name_length, file_length;
|
||||||
|
gunichar2 *name;
|
||||||
|
|
||||||
|
// gchar* name_utf8;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstAviSubtitle *avisubtitle = GST_AVI_SUBTITLE (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
|
/* we expext only one buffer packet with the whole srt/ssa file in it */
|
||||||
|
|
||||||
|
/* check the magic word "GAB2\0" */
|
||||||
|
if (GST_BUFFER_SIZE (buffer) <= 11
|
||||||
|
|| memcmp (GST_BUFFER_DATA (buffer), "GAB2\0", 5) != 0)
|
||||||
|
goto wrong_magic_word;
|
||||||
|
|
||||||
|
/* next word must be 2 */
|
||||||
|
if (GST_READ_UINT16_LE (GST_BUFFER_DATA (buffer) + 5) != 0x2)
|
||||||
|
goto wrong_fixed_word_1;
|
||||||
|
|
||||||
|
name_length = GST_READ_UINT32_LE (GST_BUFFER_DATA (buffer) + 7);
|
||||||
|
GST_LOG ("length of name: %d", name_length);
|
||||||
|
if (GST_BUFFER_SIZE (buffer) <= 17 + name_length)
|
||||||
|
goto wrong_length_1;
|
||||||
|
|
||||||
|
name = (gunichar2 *) & (GST_BUFFER_DATA (buffer)[11]);
|
||||||
|
// FIXME Take care for endianess in UTF-16
|
||||||
|
// name_utf8 = g_utf16_to_utf8( name, name_length, NULL, NULL, NULL);
|
||||||
|
// GST_LOG("avi subtitle name: %s", name_utf8);
|
||||||
|
// g_free (name_utf8);
|
||||||
|
|
||||||
|
/* next word must be 4 */
|
||||||
|
if (GST_READ_UINT16_LE (GST_BUFFER_DATA (buffer) + 11 + name_length) != 0x4)
|
||||||
|
goto wrong_fixed_word_2;
|
||||||
|
|
||||||
|
file_length =
|
||||||
|
GST_READ_UINT32_LE (GST_BUFFER_DATA (buffer) + 13 + name_length);
|
||||||
|
GST_LOG ("length srt/ssa file: %d", file_length);
|
||||||
|
|
||||||
|
if (GST_BUFFER_SIZE (buffer) != 17 + name_length + file_length)
|
||||||
|
goto wrong_total_length;
|
||||||
|
|
||||||
|
/* push the file over the src pad */
|
||||||
|
ret =
|
||||||
|
gst_pad_push (avisubtitle->src, gst_avi_subtitle_utf8_file (buffer,
|
||||||
|
17 + name_length));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* all the errors */
|
||||||
|
wrong_magic_word:
|
||||||
|
GST_ELEMENT_ERROR (avisubtitle, STREAM, DECODE, NULL, ("Wrong magic word"));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
wrong_fixed_word_1:
|
||||||
|
GST_ELEMENT_ERROR (avisubtitle, STREAM, DECODE, NULL,
|
||||||
|
("wrong fixed word: expected %d found %d", 2,
|
||||||
|
GST_READ_UINT16_LE (GST_BUFFER_DATA (buffer) + 5)));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
wrong_length_1:
|
||||||
|
GST_ELEMENT_ERROR (avisubtitle, STREAM, DECODE, NULL,
|
||||||
|
("length of the buffer is too small (%d < %d)", GST_BUFFER_SIZE (buffer),
|
||||||
|
17 + name_length));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
wrong_fixed_word_2:
|
||||||
|
GST_ELEMENT_ERROR (avisubtitle, STREAM, DECODE, NULL,
|
||||||
|
("wrong fixed word: expected %d found %d", 4,
|
||||||
|
GST_READ_UINT16_LE (GST_BUFFER_DATA (buffer) + 11 + name_length)));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
wrong_total_length:
|
||||||
|
GST_ELEMENT_ERROR (avisubtitle, STREAM, DECODE, NULL,
|
||||||
|
("buffer size is wrong: need %d bytes, have %d bytes",
|
||||||
|
17 + name_length + file_length, GST_BUFFER_SIZE (buffer)));
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avi_subtitle_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
static const GstElementDetails gst_avi_demux_details =
|
||||||
|
GST_ELEMENT_DETAILS ("Avi subtitle parser",
|
||||||
|
"Codec/Demuxer",
|
||||||
|
"Parse avi subtitle stream",
|
||||||
|
"Thijs Vermeir <thijsvermeir@gmail.com>");
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
/* add the pad templates to the element */
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&src_template));
|
||||||
|
|
||||||
|
/* set the element details */
|
||||||
|
gst_element_class_set_details (element_class, &gst_avi_demux_details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avi_subtitle_class_init (GstAviSubtitleClass * klass)
|
||||||
|
{
|
||||||
|
GST_DEBUG_CATEGORY_INIT (avisubtitle_debug, "avisubtitle", 0,
|
||||||
|
"parse avi subtitle stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_avi_subtitle_init (GstAviSubtitle * self, GstAviSubtitleClass * klass)
|
||||||
|
{
|
||||||
|
self->src = gst_pad_new_from_static_template (&src_template, "src");
|
||||||
|
gst_element_add_pad (GST_ELEMENT (self), self->src);
|
||||||
|
|
||||||
|
self->sink = gst_pad_new_from_static_template (&sink_template, "sink");
|
||||||
|
gst_element_add_pad (GST_ELEMENT (self), self->sink);
|
||||||
|
gst_pad_set_chain_function (self->sink, gst_avi_subtitle_chain);
|
||||||
|
}
|
37
gst/avi/gstavisubtitle.h
Normal file
37
gst/avi/gstavisubtitle.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
#ifndef __GSTAVISUBTITLE_H__
|
||||||
|
#define __GSTAVISUBTITLE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstAviSubtitle GstAviSubtitle;
|
||||||
|
typedef struct _GstAviSubtitleClass GstAviSubtitleClass;
|
||||||
|
|
||||||
|
#define GST_TYPE_AVI_SUBTITLE (gst_avi_subtitle_get_type ())
|
||||||
|
#define GST_AVI_SUBTITLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_AVI_SUBTITLE, GstAviSubtitle))
|
||||||
|
#define GST_AVI_SUBTITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_AVI_SUBTITLE, GstAviSubtitleClass))
|
||||||
|
#define IS_GST_AVI_SUBTITLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_AVI_SUBTITLE))
|
||||||
|
#define IS_GST_AVI_SUBTITLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_AVI_SUBTITLE))
|
||||||
|
#define GST_AVI_SUBTITLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AVI_SUBTITLE, GstAviSubtitleClass))
|
||||||
|
|
||||||
|
GType gst_avi_subtitle_get_type (void);
|
||||||
|
|
||||||
|
struct _GstAviSubtitle
|
||||||
|
{
|
||||||
|
GstElement parent;
|
||||||
|
|
||||||
|
GstPad* src;
|
||||||
|
GstPad* sink;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstAviSubtitleClass
|
||||||
|
{
|
||||||
|
GstElementClass parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif
|
|
@ -60,6 +60,7 @@ check_PROGRAMS = \
|
||||||
elements/audioamplify \
|
elements/audioamplify \
|
||||||
elements/audiodynamic \
|
elements/audiodynamic \
|
||||||
elements/avimux \
|
elements/avimux \
|
||||||
|
elements/avisubtitle \
|
||||||
elements/id3demux \
|
elements/id3demux \
|
||||||
elements/level \
|
elements/level \
|
||||||
elements/matroskamux \
|
elements/matroskamux \
|
||||||
|
|
248
tests/check/elements/avisubtitle.c
Normal file
248
tests/check/elements/avisubtitle.c
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
/* GStreamer
|
||||||
|
*
|
||||||
|
* unit test for avisubtitle
|
||||||
|
*
|
||||||
|
* Copyright (C) <2007> Thijs Vermeir <thijsvermeir@gmail.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.
|
||||||
|
*/
|
||||||
|
/* Element-Checklist-Version: 5 */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/check/gstcheck.h>
|
||||||
|
|
||||||
|
GstPad *mysinkpad;
|
||||||
|
GstPad *mysrcpad;
|
||||||
|
|
||||||
|
guint8 avisub_utf_8_with_bom[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
|
||||||
|
0x00, 0x00, 0x00, 0x04, 0x00, 0x8e, 0x00, 0x00,
|
||||||
|
0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30,
|
||||||
|
0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x2c,
|
||||||
|
0x31, 0x30, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20,
|
||||||
|
0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32,
|
||||||
|
0x2c, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x3c, 0x62,
|
||||||
|
0x3e, 0x41, 0x6e, 0x20, 0x55, 0x54, 0x46, 0x38,
|
||||||
|
0x20, 0x53, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c,
|
||||||
|
0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42,
|
||||||
|
0x4f, 0x4d, 0x3c, 0x2f, 0x62, 0x3e, 0x0d, 0x0a,
|
||||||
|
0x0d, 0x0a, 0x32, 0x0d, 0x0a, 0x30, 0x30, 0x3a,
|
||||||
|
0x30, 0x30, 0x3a, 0x30, 0x32, 0x2c, 0x31, 0x30,
|
||||||
|
0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20, 0x30, 0x30,
|
||||||
|
0x3a, 0x30, 0x30, 0x3a, 0x30, 0x34, 0x2c, 0x30,
|
||||||
|
0x30, 0x30, 0x0d, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
|
||||||
|
0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f,
|
||||||
|
0x6e, 0x41, 0x53, 0x43, 0x49, 0x49, 0x20, 0x2d,
|
||||||
|
0x20, 0xc2, 0xb5, 0xc3, 0xb6, 0xc3, 0xa4, 0xc3,
|
||||||
|
0xbc, 0xc3, 0x9f, 0x0d, 0x0a, 0x0d, 0x0a
|
||||||
|
};
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-subtitle")
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("application/x-subtitle-avi")
|
||||||
|
);
|
||||||
|
|
||||||
|
GstElement *
|
||||||
|
setup_avisubtitle ()
|
||||||
|
{
|
||||||
|
GstElement *avisubtitle;
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
GST_DEBUG ("setup_avisubtitle");
|
||||||
|
avisubtitle = gst_check_setup_element ("avisubtitle");
|
||||||
|
caps = gst_caps_new_simple ("application/x-subtitle", NULL);
|
||||||
|
mysinkpad = gst_check_setup_sink_pad (avisubtitle, &sink_template, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
caps = gst_caps_new_simple ("application/x-subtitle-avi", NULL);
|
||||||
|
mysrcpad = gst_check_setup_src_pad (avisubtitle, &src_template, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
gst_pad_set_active (mysinkpad, TRUE);
|
||||||
|
gst_pad_set_active (mysrcpad, TRUE);
|
||||||
|
return avisubtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cleanup_avisubtitle (GstElement * avisubtitle)
|
||||||
|
{
|
||||||
|
gst_pad_set_active (mysinkpad, FALSE);
|
||||||
|
gst_pad_set_active (mysrcpad, FALSE);
|
||||||
|
gst_check_teardown_sink_pad (avisubtitle);
|
||||||
|
gst_check_teardown_src_pad (avisubtitle);
|
||||||
|
gst_check_teardown_element (avisubtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_wrong_buffer (guint8 * data, guint length)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer = gst_buffer_new ();
|
||||||
|
GstElement *avisubtitle = setup_avisubtitle ();
|
||||||
|
|
||||||
|
gst_buffer_set_data (buffer, data, length);
|
||||||
|
fail_unless (gst_element_set_state (avisubtitle,
|
||||||
|
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||||
|
"could not set to playing");
|
||||||
|
gst_buffer_ref (buffer);
|
||||||
|
ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 2);
|
||||||
|
/* push the broken buffer */
|
||||||
|
fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_ERROR,
|
||||||
|
"accepted a broken buffer");
|
||||||
|
/* check if we have unreffed this buffer on failure */
|
||||||
|
ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
|
||||||
|
gst_buffer_unref (buffer);
|
||||||
|
fail_unless (gst_element_set_state (avisubtitle,
|
||||||
|
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
|
||||||
|
cleanup_avisubtitle (avisubtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_correct_buffer (guint8 * src_data, guint src_size, guint8 * dst_data,
|
||||||
|
guint dst_size)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer = gst_buffer_new ();
|
||||||
|
GstBuffer *newBuffer;
|
||||||
|
GstElement *avisubtitle = setup_avisubtitle ();
|
||||||
|
|
||||||
|
fail_unless (g_list_length (buffers) == 0, "Buffers list needs to be empty");
|
||||||
|
gst_buffer_set_data (buffer, src_data, src_size);
|
||||||
|
fail_unless (gst_element_set_state (avisubtitle,
|
||||||
|
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||||
|
"could not set to playing");
|
||||||
|
ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
|
||||||
|
fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK,
|
||||||
|
"not accepted a correct buffer");
|
||||||
|
ASSERT_BUFFER_REFCOUNT (buffer, "inbuffer", 1);
|
||||||
|
/* a new buffer is created in the list */
|
||||||
|
fail_unless (g_list_length (buffers) == 1,
|
||||||
|
"No new buffer in the buffers list");
|
||||||
|
newBuffer = GST_BUFFER (buffers->data);
|
||||||
|
buffers = g_list_remove (buffers, newBuffer);
|
||||||
|
fail_unless (g_list_length (buffers) == 0, "Buffers list needs to be empty");
|
||||||
|
fail_unless (GST_BUFFER_SIZE (newBuffer) == dst_size,
|
||||||
|
"size of the new buffer is wrong ( %d != %d)",
|
||||||
|
GST_BUFFER_SIZE (newBuffer), dst_size);
|
||||||
|
fail_unless (memcmp (GST_BUFFER_DATA (newBuffer), dst_data, dst_size) == 0,
|
||||||
|
"data of the buffer is not correct");
|
||||||
|
gst_buffer_unref (newBuffer);
|
||||||
|
fail_unless (gst_element_set_state (avisubtitle,
|
||||||
|
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null");
|
||||||
|
cleanup_avisubtitle (avisubtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GST_START_TEST (test_avisubtitle_negative)
|
||||||
|
{
|
||||||
|
guint8 wrong_magic[] =
|
||||||
|
{ 0x47, 0x41, 0x41, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00 };
|
||||||
|
guint8 wrong_fixed_word_2[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x01, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68
|
||||||
|
};
|
||||||
|
guint8 wrong_length_after_name[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68
|
||||||
|
};
|
||||||
|
guint8 wrong_fixed_word_4[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
|
||||||
|
0x00, 0x00, 0x00, 0x04, 0x01, 0x8e, 0x00, 0x00,
|
||||||
|
0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30
|
||||||
|
};
|
||||||
|
guint8 wrong_total_length[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
|
||||||
|
0x00, 0x00, 0x00, 0x04, 0x00, 0x8e, 0x00, 0x00,
|
||||||
|
0x00, 0xef, 0xbb, 0xbf, 0x31, 0x0d, 0x0a, 0x30
|
||||||
|
};
|
||||||
|
/* size of the buffer must be larger than 11 */
|
||||||
|
check_wrong_buffer (avisub_utf_8_with_bom, 11);
|
||||||
|
/* buffer must start with 'GAB2\0' */
|
||||||
|
check_wrong_buffer (wrong_magic, 14);
|
||||||
|
/* next word must be 2 */
|
||||||
|
check_wrong_buffer (wrong_fixed_word_2, 24);
|
||||||
|
/* length must be larger than the length of the name + 17 */
|
||||||
|
check_wrong_buffer (wrong_length_after_name, 24);
|
||||||
|
/* next word must be 4 */
|
||||||
|
check_wrong_buffer (wrong_fixed_word_4, 36);
|
||||||
|
/* check wrong total length */
|
||||||
|
check_wrong_buffer (wrong_total_length, 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_avisubtitle_positive)
|
||||||
|
{
|
||||||
|
guint8 avisub_utf_8_without_bom[] = {
|
||||||
|
0x47, 0x41, 0x42, 0x32, 0x00, 0x02, 0x00, 0x10,
|
||||||
|
0x00, 0x00, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x67,
|
||||||
|
0x00, 0x6c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x68,
|
||||||
|
0x00, 0x00, 0x00, 0x04, 0x00, 0x8b, 0x00, 0x00,
|
||||||
|
0x00, 0x31, 0x0d, 0x0a, 0x30,
|
||||||
|
0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x2c,
|
||||||
|
0x31, 0x30, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20,
|
||||||
|
0x30, 0x30, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32,
|
||||||
|
0x2c, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x3c, 0x62,
|
||||||
|
0x3e, 0x41, 0x6e, 0x20, 0x55, 0x54, 0x46, 0x38,
|
||||||
|
0x20, 0x53, 0x75, 0x62, 0x74, 0x69, 0x74, 0x6c,
|
||||||
|
0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42,
|
||||||
|
0x4f, 0x4d, 0x3c, 0x2f, 0x62, 0x3e, 0x0d, 0x0a,
|
||||||
|
0x0d, 0x0a, 0x32, 0x0d, 0x0a, 0x30, 0x30, 0x3a,
|
||||||
|
0x30, 0x30, 0x3a, 0x30, 0x32, 0x2c, 0x31, 0x30,
|
||||||
|
0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x20, 0x30, 0x30,
|
||||||
|
0x3a, 0x30, 0x30, 0x3a, 0x30, 0x34, 0x2c, 0x30,
|
||||||
|
0x30, 0x30, 0x0d, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
|
||||||
|
0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f,
|
||||||
|
0x6e, 0x41, 0x53, 0x43, 0x49, 0x49, 0x20, 0x2d,
|
||||||
|
0x20, 0xc2, 0xb5, 0xc3, 0xb6, 0xc3, 0xa4, 0xc3,
|
||||||
|
0xbc, 0xc3, 0x9f, 0x0d, 0x0a, 0x0d, 0x0a
|
||||||
|
};
|
||||||
|
check_correct_buffer (avisub_utf_8_with_bom, 175, avisub_utf_8_with_bom + 36,
|
||||||
|
139);
|
||||||
|
check_correct_buffer (avisub_utf_8_without_bom, 172,
|
||||||
|
avisub_utf_8_without_bom + 33, 139);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
Suite *
|
||||||
|
avisubtitle_suite (void)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create ("avisubtitle");
|
||||||
|
TCase *tc_chain = tcase_create ("general");
|
||||||
|
|
||||||
|
suite_add_tcase (s, tc_chain);
|
||||||
|
tcase_add_test (tc_chain, test_avisubtitle_negative);
|
||||||
|
tcase_add_test (tc_chain, test_avisubtitle_positive);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_CHECK_MAIN (avisubtitle);
|
|
@ -36,7 +36,7 @@
|
||||||
#define GST_LICENSE "LGPL"
|
#define GST_LICENSE "LGPL"
|
||||||
|
|
||||||
/* package name in plugins */
|
/* package name in plugins */
|
||||||
#define GST_PACKAGE_NAME "GStreamer Good Plug-ins source release"
|
#define GST_PACKAGE_NAME "GStreamer Good Plug-ins CVS/prerelease"
|
||||||
|
|
||||||
/* package origin */
|
/* package origin */
|
||||||
#define GST_PACKAGE_ORIGIN "Unknown package origin"
|
#define GST_PACKAGE_ORIGIN "Unknown package origin"
|
||||||
|
@ -244,13 +244,13 @@
|
||||||
#define PACKAGE_NAME "GStreamer Good Plug-ins"
|
#define PACKAGE_NAME "GStreamer Good Plug-ins"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* Define to the full name and version of this package. */
|
||||||
#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.6"
|
#define PACKAGE_STRING "GStreamer Good Plug-ins 0.10.6.1"
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
/* Define to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "gst-plugins-good"
|
#define PACKAGE_TARNAME "gst-plugins-good"
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "0.10.6"
|
#define PACKAGE_VERSION "0.10.6.1"
|
||||||
|
|
||||||
/* Define the plugin directory */
|
/* Define the plugin directory */
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
@ -266,7 +266,7 @@
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "0.10.6"
|
#define VERSION "0.10.6.1"
|
||||||
|
|
||||||
/* Define to 1 if your processor stores words with the most significant byte
|
/* Define to 1 if your processor stores words with the most significant byte
|
||||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||||
|
|
Loading…
Reference in a new issue