summaryrefslogtreecommitdiff
path: root/gst/cdxaparse/gstcdxaparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/cdxaparse/gstcdxaparse.c')
-rw-r--r--gst/cdxaparse/gstcdxaparse.c585
1 files changed, 0 insertions, 585 deletions
diff --git a/gst/cdxaparse/gstcdxaparse.c b/gst/cdxaparse/gstcdxaparse.c
deleted file mode 100644
index 4334362e0..000000000
--- a/gst/cdxaparse/gstcdxaparse.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * <2002> Wim Taymans <wim.taymans@chello.be>
- * <2006> Tim-Philipp Müller <tim centricular net>
- *
- * 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., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
- * with newer GLib versions (>= 2.31.0) */
-#define GLIB_DISABLE_DEPRECATION_WARNINGS
-
-#include <string.h>
-
-#include "gstcdxaparse.h"
-#include "gstvcdparse.h"
-
-#include <gst/riff/riff-ids.h>
-#include <gst/riff/riff-read.h>
-
-GST_DEBUG_CATEGORY (vcdparse_debug);
-
-GST_DEBUG_CATEGORY_STATIC (cdxaparse_debug);
-#define GST_CAT_DEFAULT cdxaparse_debug
-
-static gboolean gst_cdxa_parse_sink_activate (GstPad * sinkpad);
-static void gst_cdxa_parse_loop (GstPad * sinkpad);
-static gboolean gst_cdxa_parse_sink_activate_pull (GstPad * sinkpad,
- gboolean active);
-static GstStateChangeReturn gst_cdxa_parse_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean gst_cdxa_parse_src_event (GstPad * srcpad, GstEvent * event);
-static gboolean gst_cdxa_parse_src_query (GstPad * srcpad, GstQuery * query);
-
-static GstStaticPadTemplate sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-cdxa")
- );
-
-static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/mpeg, " "systemstream = (boolean) TRUE")
- );
-
-GST_BOILERPLATE (GstCDXAParse, gst_cdxa_parse, GstElement, GST_TYPE_ELEMENT);
-
-static void
-gst_cdxa_parse_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_static_metadata (element_class, "(S)VCD parser",
- "Codec/Parser",
- "Parse a .dat file from (S)VCD into raw MPEG-1",
- "Wim Taymans <wim.taymans@tvd.be>");
-
- /* register src pads */
- gst_element_class_add_static_pad_template (element_class,
- &sink_template_factory);
- gst_element_class_add_static_pad_template (element_class,
- &src_template_factory);
-}
-
-static void
-gst_cdxa_parse_class_init (GstCDXAParseClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_cdxa_parse_change_state);
-}
-
-static void
-gst_cdxa_parse_init (GstCDXAParse * cdxaparse, GstCDXAParseClass * klass)
-{
- GstCaps *caps;
-
- cdxaparse->sinkpad =
- gst_pad_new_from_static_template (&sink_template_factory, "sink");
- gst_pad_set_activate_function (cdxaparse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_cdxa_parse_sink_activate));
- gst_pad_set_activatepull_function (cdxaparse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_cdxa_parse_sink_activate_pull));
-
- gst_element_add_pad (GST_ELEMENT (cdxaparse), cdxaparse->sinkpad);
-
- cdxaparse->srcpad =
- gst_pad_new_from_static_template (&src_template_factory, "src");
-
- gst_pad_set_event_function (cdxaparse->srcpad,
- GST_DEBUG_FUNCPTR (gst_cdxa_parse_src_event));
- gst_pad_set_query_function (cdxaparse->srcpad,
- GST_DEBUG_FUNCPTR (gst_cdxa_parse_src_query));
-
- caps = gst_caps_new_simple ("video/mpeg",
- "systemstream", G_TYPE_BOOLEAN, TRUE, NULL);
- gst_pad_use_fixed_caps (cdxaparse->srcpad);
- gst_pad_set_caps (cdxaparse->srcpad, caps);
- gst_caps_unref (caps);
- gst_element_add_pad (GST_ELEMENT (cdxaparse), cdxaparse->srcpad);
-
-
- cdxaparse->state = GST_CDXA_PARSE_START;
- cdxaparse->offset = 0;
- cdxaparse->datasize = 0;
- cdxaparse->datastart = -1;
-}
-
-#define HAVE_FOURCC(data,fourcc) (GST_READ_UINT32_LE((data))==(fourcc))
-
-static gboolean
-gst_cdxa_parse_stream_init (GstCDXAParse * cdxa)
-{
- GstFlowReturn flow_ret;
- GstBuffer *buf = NULL;
- guint8 *data;
-
- flow_ret = gst_pad_pull_range (cdxa->sinkpad, cdxa->offset, 12, &buf);
- if (flow_ret != GST_FLOW_OK)
- return flow_ret;
-
- if (GST_BUFFER_SIZE (buf) < 12)
- goto wrong_type;
-
- data = GST_BUFFER_DATA (buf);
- if (!HAVE_FOURCC (data, GST_RIFF_TAG_RIFF)) {
- GST_ERROR_OBJECT (cdxa, "Not a RIFF file");
- goto wrong_type;
- }
-
- if (!HAVE_FOURCC (data + 8, GST_RIFF_RIFF_CDXA)) {
- GST_ERROR_OBJECT (cdxa, "RIFF file does not have CDXA content");
- goto wrong_type;
- }
-
- cdxa->offset += 12;
- gst_buffer_unref (buf);
-
- return TRUE;
-
-wrong_type:
-
- GST_ELEMENT_ERROR (cdxa, STREAM, WRONG_TYPE, (NULL), (NULL));
- gst_buffer_unref (buf);
- return FALSE;
-}
-
-static gboolean
-gst_cdxa_parse_sink_activate (GstPad * sinkpad)
-{
- GstCDXAParse *cdxa = GST_CDXA_PARSE (GST_PAD_PARENT (sinkpad));
-
- if (!gst_pad_check_pull_range (sinkpad) ||
- !gst_pad_activate_pull (sinkpad, TRUE)) {
- GST_DEBUG_OBJECT (cdxa, "No pull mode");
- return FALSE;
- }
-
- /* If we can activate pull_range upstream, then read the header
- * and see if it's really a RIFF CDXA file. */
- GST_DEBUG_OBJECT (cdxa, "Activated pull mode. Reading RIFF header");
- if (!gst_cdxa_parse_stream_init (cdxa))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-gst_cdxa_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
-{
- if (active) {
- /* if we have a scheduler we can start the task */
- gst_pad_start_task (sinkpad, (GstTaskFunction) gst_cdxa_parse_loop,
- sinkpad, NULL);
- } else {
- gst_pad_stop_task (sinkpad);
- }
-
- return TRUE;
-}
-
-/*
- * A sector is 2352 bytes long and is composed of:
- *
- * ! sync ! header ! subheader ! data ... ! edc !
- * ! 12 bytes ! 4 bytes ! 8 bytes ! 2324 bytes ! 4 bytes !
- * !-------------------------------------------------------!
- *
- * We strip the data out of it and send it to the srcpad.
- *
- * sync : 00 FF FF FF FF FF FF FF FF FF FF 00
- * header : hour minute second mode
- * sub-header : track channel sub_mode coding repeat (4 bytes)
- * edc : checksum
- */
-
-/* FIXME: use define from gstcdxastrip.h */
-#define GST_CDXA_SECTOR_SIZE 2352
-#define GST_CDXA_DATA_SIZE 2324
-#define GST_CDXA_HEADER_SIZE 24
-
-/* FIXME: use version from gstcdxastrip.c */
-static GstBuffer *
-gst_cdxa_parse_strip (GstBuffer * buf)
-{
- GstBuffer *sub;
-
- g_assert (GST_BUFFER_SIZE (buf) >= GST_CDXA_SECTOR_SIZE);
-
- /* Skip CDXA headers, only keep data.
- * FIXME: check sync, resync, ... */
- sub = gst_buffer_create_sub (buf, GST_CDXA_HEADER_SIZE, GST_CDXA_DATA_SIZE);
- gst_buffer_unref (buf);
-
- return sub;
-}
-
-/* -1 = no sync (discard buffer),
- * otherwise offset indicates syncpoint in buffer.
- */
-
-static gint
-gst_cdxa_parse_sync (GstBuffer * buf)
-{
- const guint8 sync_marker[12] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
- };
- guint8 *data;
- guint size;
-
- size = GST_BUFFER_SIZE (buf);
- data = GST_BUFFER_DATA (buf);
-
- while (size >= 12) {
- if (memcmp (data, sync_marker, 12) == 0) {
- return (gint) (data - GST_BUFFER_DATA (buf));
- }
- --size;
- ++data;
- }
- return -1;
-}
-
-static void
-gst_cdxa_parse_loop (GstPad * sinkpad)
-{
- GstFlowReturn flow_ret;
- GstCDXAParse *cdxa;
- GstBuffer *buf = NULL;
- gint sync_offset = -1;
-
- cdxa = GST_CDXA_PARSE (GST_PAD_PARENT (sinkpad));
-
- if (cdxa->datasize <= 0) {
- GstFormat format = GST_FORMAT_BYTES;
- GstPad *peer;
-
- if ((peer = gst_pad_get_peer (sinkpad))) {
- if (!gst_pad_query_duration (peer, &format, &cdxa->datasize)) {
- GST_DEBUG_OBJECT (cdxa, "Failed to query upstream size!");
- gst_object_unref (peer);
- goto pause;
- }
- gst_object_unref (peer);
- }
- GST_DEBUG_OBJECT (cdxa, "Upstream size: %" G_GINT64_FORMAT, cdxa->datasize);
- }
-
- do {
- guint req;
-
- req = 8 + GST_CDXA_SECTOR_SIZE; /* riff chunk header = 8 bytes */
-
- buf = NULL;
- flow_ret = gst_pad_pull_range (cdxa->sinkpad, cdxa->offset, req, &buf);
-
- if (flow_ret != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (cdxa, "Pull flow: %s", gst_flow_get_name (flow_ret));
- goto pause;
- }
-
- if (GST_BUFFER_SIZE (buf) < req) {
- GST_DEBUG_OBJECT (cdxa, "Short read, only got %u/%u bytes",
- GST_BUFFER_SIZE (buf), req);
- goto eos;
- }
-
- sync_offset = gst_cdxa_parse_sync (buf);
- gst_buffer_unref (buf);
- buf = NULL;
-
- if (sync_offset >= 0)
- break;
-
- cdxa->offset += req;
- cdxa->bytes_skipped += req;
- } while (1);
-
- cdxa->offset += sync_offset;
- cdxa->bytes_skipped += sync_offset;
-
- /* first sync frame? */
- if (cdxa->datastart < 0) {
- GST_LOG_OBJECT (cdxa, "datastart=0x%" G_GINT64_MODIFIER "x", cdxa->offset);
- cdxa->datastart = cdxa->offset;
- cdxa->bytes_skipped = 0;
- cdxa->bytes_sent = 0;
- }
-
- GST_DEBUG_OBJECT (cdxa, "pulling buffer at offset 0x%" G_GINT64_MODIFIER "x",
- cdxa->offset);
-
- buf = NULL;
- flow_ret = gst_pad_pull_range (cdxa->sinkpad, cdxa->offset,
- GST_CDXA_SECTOR_SIZE, &buf);
-
- if (flow_ret != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (cdxa, "Flow: %s", gst_flow_get_name (flow_ret));
- goto pause;
- }
-
- if (GST_BUFFER_SIZE (buf) < GST_CDXA_SECTOR_SIZE) {
- GST_DEBUG_OBJECT (cdxa, "Short read, only got %u/%u bytes",
- GST_BUFFER_SIZE (buf), GST_CDXA_SECTOR_SIZE);
- goto eos;
- }
-
- buf = gst_cdxa_parse_strip (buf);
-
- GST_DEBUG_OBJECT (cdxa, "pushing buffer %p", buf);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (cdxa->srcpad));
-
- cdxa->offset += GST_BUFFER_SIZE (buf);
- cdxa->bytes_sent += GST_BUFFER_SIZE (buf);
-
- flow_ret = gst_pad_push (cdxa->srcpad, buf);
- if (flow_ret != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (cdxa, "Push flow: %s", gst_flow_get_name (flow_ret));
- goto pause;
- }
-
- return;
-
-eos:
- {
- GST_DEBUG_OBJECT (cdxa, "Sending EOS");
- if (buf)
- gst_buffer_unref (buf);
- buf = NULL;
- gst_pad_push_event (cdxa->srcpad, gst_event_new_eos ());
- /* fallthrough */
- }
-pause:
- {
- GST_DEBUG_OBJECT (cdxa, "Pausing");
- gst_pad_pause_task (cdxa->sinkpad);
- return;
- }
-}
-
-static gint64
-gst_cdxa_parse_convert_src_to_sink_offset (GstCDXAParse * cdxa, gint64 src)
-{
- gint64 sink;
-
- sink = src + cdxa->datastart;
- sink = gst_util_uint64_scale (sink, GST_CDXA_SECTOR_SIZE, GST_CDXA_DATA_SIZE);
-
- /* FIXME: take into account skipped bytes */
-
- GST_DEBUG_OBJECT (cdxa, "src offset=%" G_GINT64_FORMAT ", sink offset=%"
- G_GINT64_FORMAT, src, sink);
-
- return sink;
-}
-
-static gint64
-gst_cdxa_parse_convert_sink_to_src_offset (GstCDXAParse * cdxa, gint64 sink)
-{
- gint64 src;
-
- src = sink - cdxa->datastart;
- src = gst_util_uint64_scale (src, GST_CDXA_DATA_SIZE, GST_CDXA_SECTOR_SIZE);
-
- /* FIXME: take into account skipped bytes */
-
- GST_DEBUG_OBJECT (cdxa, "sink offset=%" G_GINT64_FORMAT ", src offset=%"
- G_GINT64_FORMAT, sink, src);
-
- return src;
-}
-
-static gboolean
-gst_cdxa_parse_do_seek (GstCDXAParse * cdxa, GstEvent * event)
-{
- GstSeekFlags flags;
- GstSeekType start_type;
- GstFormat format;
- gint64 start, off, upstream_size;
-
- gst_event_parse_seek (event, NULL, &format, &flags, &start_type, &start,
- NULL, NULL);
-
- if (format != GST_FORMAT_BYTES) {
- GST_DEBUG_OBJECT (cdxa, "Can only handle seek in BYTES format");
- return FALSE;
- }
-
- if (start_type != GST_SEEK_TYPE_SET) {
- GST_DEBUG_OBJECT (cdxa, "Can only handle seek from start (SEEK_TYPE_SET)");
- return FALSE;
- }
-
- GST_OBJECT_LOCK (cdxa);
- off = gst_cdxa_parse_convert_src_to_sink_offset (cdxa, start);
- upstream_size = cdxa->datasize;
- GST_OBJECT_UNLOCK (cdxa);
-
- if (off >= upstream_size) {
- GST_DEBUG_OBJECT (cdxa, "Invalid target offset %" G_GINT64_FORMAT ", file "
- "is only %" G_GINT64_FORMAT " bytes in size", off, upstream_size);
- return FALSE;
- }
-
- /* unlock upstream pull_range */
- gst_pad_push_event (cdxa->sinkpad, gst_event_new_flush_start ());
-
- /* make sure our loop function exits */
- gst_pad_push_event (cdxa->srcpad, gst_event_new_flush_start ());
-
- /* wait for streaming to finish */
- GST_PAD_STREAM_LOCK (cdxa->sinkpad);
-
- /* prepare for streaming again */
- gst_pad_push_event (cdxa->sinkpad, gst_event_new_flush_stop ());
- gst_pad_push_event (cdxa->srcpad, gst_event_new_flush_stop ());
-
- gst_pad_push_event (cdxa->srcpad,
- gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
- start, GST_CLOCK_TIME_NONE, 0));
-
- GST_OBJECT_LOCK (cdxa);
- cdxa->offset = off;
- GST_OBJECT_UNLOCK (cdxa);
-
- /* and restart */
- gst_pad_start_task (cdxa->sinkpad,
- (GstTaskFunction) gst_cdxa_parse_loop, cdxa->sinkpad, NULL);
-
- GST_PAD_STREAM_UNLOCK (cdxa->sinkpad);
- return TRUE;
-}
-
-static gboolean
-gst_cdxa_parse_src_event (GstPad * srcpad, GstEvent * event)
-{
- GstCDXAParse *cdxa = GST_CDXA_PARSE (gst_pad_get_parent (srcpad));
- gboolean res = FALSE;
-
- GST_DEBUG_OBJECT (cdxa, "Handling %s event", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- res = gst_cdxa_parse_do_seek (cdxa, event);
- break;
- default:
- res = gst_pad_event_default (srcpad, event);
- break;
- }
-
- gst_object_unref (cdxa);
- return res;
-}
-
-static gboolean
-gst_cdxa_parse_src_query (GstPad * srcpad, GstQuery * query)
-{
- GstCDXAParse *cdxa = GST_CDXA_PARSE (gst_pad_get_parent (srcpad));
- gboolean res = FALSE;
-
- GST_DEBUG_OBJECT (cdxa, "Handling %s query",
- gst_query_type_get_name (GST_QUERY_TYPE (query)));
-
- res = gst_pad_query_default (srcpad, query);
-
- if (res) {
- GstFormat format;
- gint64 val;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_DURATION:
- gst_query_parse_duration (query, &format, &val);
- if (format == GST_FORMAT_BYTES) {
- val = gst_cdxa_parse_convert_sink_to_src_offset (cdxa, val);
- gst_query_set_duration (query, format, val);
- }
- break;
- case GST_QUERY_POSITION:
- gst_query_parse_position (query, &format, &val);
- if (format == GST_FORMAT_BYTES) {
- val = gst_cdxa_parse_convert_sink_to_src_offset (cdxa, val);
- gst_query_set_position (query, format, val);
- }
- break;
- default:
- break;
- }
- }
-
- gst_object_unref (cdxa);
- return res;
-}
-
-static GstStateChangeReturn
-gst_cdxa_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstCDXAParse *cdxa = GST_CDXA_PARSE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- cdxa->state = GST_CDXA_PARSE_START;
- break;
- default:
- break;
- }
-
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- cdxa->state = GST_CDXA_PARSE_START;
- cdxa->datasize = 0;
- cdxa->datastart = -1;
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (cdxaparse_debug, "cdxaparse", 0, "CDXA Parser");
- GST_DEBUG_CATEGORY_INIT (vcdparse_debug, "vcdparse", 0, "VCD Parser");
-
- if (!gst_element_register (plugin, "cdxaparse", GST_RANK_PRIMARY,
- GST_TYPE_CDXA_PARSE))
- return FALSE;
- if (!gst_element_register (plugin, "vcdparse", GST_RANK_PRIMARY,
- GST_TYPE_VCD_PARSE))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- cdxaparse,
- "Parse a .dat file (VCD) into raw mpeg1",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)