--- a/QtGSTPlayer/QtGSTPlayer.pro Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-######################################################################
-# Automatically generated by qmake (2.01a) Wed Feb 17 14:34:47 2010
-######################################################################
-
-
-# ============================================================================
-# Name : QtGSTPlayer.pro
-# Part of : LibHb / gstplayer
-# Description : Project definition file for simple gstplayer
-# Version : %version: 1 %
-#
-# Copyright ? 2008 Nokia. All rights reserved.
-# This material, including documentation and any related computer
-# programs, is protected by copyright controlled by Nokia. All
-# rights are reserved. Copying, including reproducing, storing,
-# adapting or translating, any or all of this material requires the
-# prior written consent of Nokia. This material also contains
-# confidential information which may not be disclosed to others
-# without the prior written consent of Nokia.
-# ============================================================================
-#
-
-TEMPLATE = app
-TARGET =
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp folderview.cpp views.cpp record_play.c
-HEADERS += folderview.h views.h
-
-RESOURCES += QtGSTPlayer.qrc
-
--- a/QtGSTPlayer/QtGSTPlayer.qrc Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-<RCC>
- <qresource prefix="/QtGSTPlayer" >
- <file>folder.png</file>
- <file>settings.png</file>
- </qresource>
-</RCC>
Binary file QtGSTPlayer/folder.png has changed
--- a/QtGSTPlayer/folderview.cpp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-#include <QModelIndex>
-#include <QDirModel>
-#include <QApplication>
-
-//#include <hbformitem.h>
-//#include <hbformview.h>
-#include <hblistview.h>
-#include <hblistviewitem.h>
-#include <hbmenu.h>
-#include <hbmainwindow.h>
-
-#include <QDebug>
-#include <QAction>
-#include <HbAction>
-#include "folderview.h"
-#include "views.h"
-#include <HbAbstractViewItem>
-#include <QTimer>
-#include <hbnotificationdialog.h>
-/*! Constructor of FolderView.
- */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-int mCurrentState = 0;
-
-#ifdef __cplusplus
-}
-#endif
-//extern int mCurrentState;
-
-FolderView::FolderView(QGraphicsItem *parent)
- : HbView(parent),mModel( NULL ), mFolderPath("c:\\data\\Sounds\\Digital\\"),mTimer(NULL),mIsRecording( FALSE )
-{
- mCurrentState = NONE;
-
- // Create a main widget for this view
- // In this case, list view is appropriate
- // Note: HbListView is not derived from HbView,
- // this is just like any other Hb widget but with a feature of
- // model-view separation
- mFileList = new HbListView(this);
-
- // Create a model to set for the list view
- mModel = new QDirModel(this);
- mFileList->setModel(mModel);
-
- // Setting initial path for folder list
- mFileList->setRootIndex(mModel->index(mFolderPath));
- //mFileList->
- // Setting the main widget for this view
- setWidget(mFileList);
- //int x = mFileList->indexCount();
- QObject::connect(mFileList, SIGNAL(pressed(const QModelIndex)), this, SLOT(item_pressed(const QModelIndex)));
-
- // add menu
- HbMenu* menu1 = menu()->addMenu(tr("Record"));
-
- HbAction* menu1_Action = new HbAction(tr("RAW"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_RAW()));
- menu1->addAction( menu1_Action );
-
- menu1_Action = new HbAction(tr("WAV"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_WAV()));
- menu1->addAction( menu1_Action );
-
- //create action Nokia India sub menu item.
- menu1_Action = new HbAction(tr("AMR"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_AMR()));
- menu1->addAction( menu1_Action );
-
- menu1_Action = new HbAction(tr("G711"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_G711()));
- menu1->addAction( menu1_Action );
-
- menu1_Action = new HbAction(tr("AAC"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_AAC()));
- menu1->addAction( menu1_Action );
- menu1_Action = new HbAction(tr("G729"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_G729()));
- menu1->addAction( menu1_Action );
-
- menu1_Action = new HbAction(tr("ILBC"), this);
- connect(menu1_Action, SIGNAL(triggered()), this, SLOT(record_ILBC()));
- menu1->addAction( menu1_Action );
-
-
-
- //menu()->addAction(tr("Play"), this, SLOT(play()));
- menu()->addAction(tr("Stop"), this, SLOT(stop()));
- menu()->addAction(tr("Pause"), this, SLOT(pause()));
- menu()->addAction(tr("Resume"), this, SLOT(resume()));
- menu()->addAction(tr("Exit"), qApp, SLOT(quit()));
-
-
- /// timer required to get the glib events
- mTimer = new QTimer(this);
- connect(mTimer, SIGNAL(timeout()), this, SLOT(timertimeout()));
- mTimer->start(10);
-
-}
-
-FolderView::~FolderView()
-{
- if(mCurrentState != NONE)
- gst_unref();
-delete mFileList;
-delete mModel;
-mTimer->stop();
-delete mTimer;
-}
-
-
-void FolderView::folderViewTriggered()
-{
- mainWindow()->setCurrentView(Views::folderView());
-}
-
-/*void FolderView::settingsViewTriggered()
-{
- mainWindow()->setCurrentView(Views::settingsView());
-}*/
-
-void FolderView::showNote(const int err)
-{
- if(err)
- {
- HbNotificationDialog* notifyDialog = new HbNotificationDialog;
- notifyDialog->setTimeout(HbPopup::StandardTimeout);
- QString strong;
- QString sprint= strong.sprintf("Format Not supported(%d)",err);
- notifyDialog->setTitleTextWrapping(Hb::TextWordWrap);
- notifyDialog->setTitle(QString("Error"));
- notifyDialog->setWrapMode(Hb::TextWordWrap);
- notifyDialog->setText(sprint);
-
- notifyDialog->exec();
- delete notifyDialog;
- }
-}
-void FolderView::item_pressed(const QModelIndex &index)
-{
- if( mIsRecording )
- {
- return;
- }
- QVariant variant=index.data();
- QString str = variant.toString();
-
-
- QString fullpath = mFolderPath;
- fullpath.append( str );
-
- TBuf16<1024> buf16;
- buf16.Copy( (TUint16*)fullpath.data_ptr()->data ,fullpath.data_ptr()->size );
- TBuf8<1024> buf8;
- buf8.Copy( buf16 );
-
- if( NONE != mCurrentState )
- {
- gst_unref();
- }
-
- int err = gst_play_file( (char*)buf8.PtrZ() );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- }
- else
- {
- mCurrentState = PLAYING;
- }
-
-}
-void FolderView::pause()
-{
- if( PLAYING == mCurrentState ){
- gst_pause();
- mCurrentState = PAUSE;
- }
-}
-
-void FolderView::resume()
-{
- if( PAUSE == mCurrentState ){
- gst_resume();
- mCurrentState = PLAYING;
- }
-}
-
-void FolderView::stop()
-{
- if( mIsRecording == TRUE )
- {
- gst_record_stop();
-
- if( mModel )
- delete mModel;
-
- mModel = new QDirModel(this);
- mFileList->setModel(mModel);
-
- mFileList->reset();
- mFileList->setRootIndex(mModel->index(mFolderPath));
-// mFileList->show();
-// int x = mFileList->indexCount();
- //setWidget(mFileList);
- mIsRecording = FALSE;
- return;
- }
- if( PLAYING == mCurrentState || PAUSE == mCurrentState ){
- gst_unref();
- mCurrentState = NONE;
- }
-}
-
-void FolderView::record_AMR()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_AMR );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-
-void FolderView::record_WAV()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_WAV );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- //gst_record_wav();
- }
-}
-
-void FolderView::record_RAW()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_RAW );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-
-void FolderView::record_G711()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_G711 );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-
-void FolderView::record_G729()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_G729 );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-
-void FolderView::record_ILBC()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_ILBC );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-
-void FolderView::record_AAC()
-{
- if( mCurrentState == NONE ){
- int err = gst_record_file( RECORD_AAC );
- if(err)
- {
- showNote(err);
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
- else
- {
- mCurrentState = PLAYING;
- mIsRecording = TRUE;
- }
- }
-}
-void FolderView::timertimeout()
-{
- if( PLAYING == mCurrentState ){
- gst_get_events();
- }
-
- if( STOP == mCurrentState ){
- gst_unref();
- mCurrentState = NONE;
- mIsRecording = FALSE;
- }
-}
--- a/QtGSTPlayer/folderview.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-#ifndef FOLDERVIEW_H
-#define FOLDERVIEW_H
-
-#include <hbview.h>
-//#include <hbformview.h>
-
-#include "record_play.h"
-
-QT_BEGIN_NAMESPACE
-class QDirModel;
-QT_END_NAMESPACE
-
-//class HbFormItem;
-class HbListView;
-
-class FolderView : public HbView
-{
- Q_OBJECT
-
-public:
- explicit FolderView(QGraphicsItem *parent = 0);
- ~FolderView();
-public slots:
- void folderViewTriggered();
- //void settingsViewTriggered();
- void item_pressed(const QModelIndex &index);
-//
- void record_AMR();
- void record_WAV();
- void record_RAW();
- void record_G711();
- void record_G729();
- void record_ILBC();
- void record_AAC();
-
- void pause();
- void resume();
- void stop();
- void timertimeout();
- void showNote(const int err);
-
-//void record_file( int type );
-
-
-private:
- HbListView *mFileList;
-
-//signals:
-// void pressed(const QModelIndex &index);
-// void released(const QModelIndex &index);
-// void activated(const QModelIndex &index);
-// void longPressed(HbAbstractViewItem *item, const QPointF &coords);
-
- QDirModel *mModel;
- QString mFolderPath;
- QTimer *mTimer;
- bool mIsRecording;
-
-
- //state st;
-
-};
-
-#endif // FOLDERVIEW_H
--- a/QtGSTPlayer/main.cpp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*! This is an example application demonstrating how a simple Hb
- application is created. This application implements a folder
- browser. The application creates two views. The main view (Folder
- view) shows the folder contents. The second view (Settings view) can
- be used to set the path which is shown in the Folder view. Settings
- view uses the HbFormView. Folder view inherits HbView and implements
- a couple of methods to populate the Folder view. */
-
-#include <hbapplication.h>
-#include <hbmainwindow.h>
-#include <hbmenu.h>
-#include <hbaction.h>
-#include <hbtoolbar.h>
-
-
-#include <gst/gst_global.h>
-#include <stdlib.h>
-#include <gst/gst.h>
-
-#include "folderview.h"
-#include "views.h"
-
-int main(int argc, char *argv[])
-{
- // Create HbApplication
- gst_init (&argc, &argv);
- HbApplication a(argc, argv);
- a.setApplicationName(QObject::tr("Folder Browser"));
- //LOG(_L("Entering main.cpp"));
-
- // Create main window
- HbMainWindow mainWindow;
-
- // Create View#1 : Folder view
- HbView *folderView = new FolderView;
- // Title pane text
- folderView->setTitle(QObject::tr("QtGSTPlayer"));
-
- // Add two views to main window,
- // the adding order determines which one is shown first
-
- mainWindow.addView(folderView);
- /*mainWindow.addView(settingsView);*/
-
- // Store the mainwindow ptr.
- Views::win = &mainWindow;
-
- // Show main window
- mainWindow.show();
-
- return a.exec();
-}
--- a/QtGSTPlayer/record_play.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,855 +0,0 @@
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <gst/gst.h>
-#include "record_play.h"
-
-
-GstElement *bin;
-extern int mCurrentState;
-
-static GstElement *
-create_video_output ()
-{
- static gboolean have_video = FALSE;
- GstBin *bin;
- GstElement *queue, *sink;
- GstPad *pad;
-
- if (have_video) {
- //g_print ("Already playing a video stream. Ignoring this one\n");
- return NULL;
- }
-
- /* create a new bin to hold the elements */
- if((bin = (GstBin*) gst_bin_new (NULL)) == NULL)
- //bin = (GstBin*) gst_pipeline_new("pipeline");
- return NULL;
-
- /* Queue to ensure all streams can push data */
- queue = gst_element_factory_make ("queue", "q");
- if(queue == NULL)
- return NULL;/* Queue should always be available */
- /* Set the queue to buffer 1/10 of a second of raw video */
- g_object_set (queue, "max-size-time", (GstClockTime) GST_SECOND / 10,
- "max-size-bytes", 0, "max-size-buffers", 0, NULL);
-
-// cs = gst_element_factory_make ("ffmpegcolorspace", "cs");
-// if (!cs)
-// goto no_output;
-
- /* and a video sink */
- sink = gst_element_factory_make ("fakesink"/*autovideosink*/, "sink");
- if (!sink)
- goto no_output;
-
- /* add objects to the main pipeline */
- gst_bin_add_many (GST_BIN (bin), queue, sink, NULL);
-
- /* Link the elements */
- gst_element_link_many (queue, sink, NULL);
-
- /* Retrieve the sinkpad from the queue and 'ghost' it onto
- * the bin so that the caller can find it generically */
- pad = gst_element_get_pad (queue, "sink");
- gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
- gst_object_unref (pad);
-
- //have_video = TRUE;
-
- return GST_ELEMENT (bin);
-
- /* ERRORS */
-no_output:
- {
- //g_print ("Could not create either ffmpegcolorspace or autovideosink for output");
- return NULL;
- }
-}
-
-static GstElement *
-create_audio_output ()
-{
- static gboolean have_audio = FALSE;
- GstBin *bin;
- GstElement *queue, *audioconvert,*audioresample, *sink;
- GstPad *pad;
-
- if (have_audio) {
- //g_print ("Already playing an audio stream. Ignoring this one\n");
- return NULL;
- }
-
- /* create a new bin to hold the elements */
- bin = (GstBin*) gst_bin_new (NULL);
- if(!bin)
- goto no_output;
-
- /* Queue to ensure all streams can push data */
- queue = gst_element_factory_make ("queue", "q");
- if (!queue) /* Queue should always be available */
- goto no_output;
- /* Set the queue to buffer 1/10 of a second of raw audio */
- g_object_set (queue, "max-size-time", (GstClockTime) GST_SECOND / 10,
- "max-size-bytes", 0, "max-size-buffers", 0, NULL);
-
- /* an audio converter to convert floating-point audio samples to int format */
- audioconvert = gst_element_factory_make ("audioconvert", "ac");
- if (!audioconvert)
- goto no_output;
-
- /* an audio converter to convert floating-point audio samples to int format */
- audioresample = gst_element_factory_make ("audioresample", "audioresample");
- if (!audioresample)
- goto no_output;
-
- /* and an audio sink */
- sink = gst_element_factory_make ("autoaudiosink", "sink");
- if (!sink)
- goto no_output;
-
- /* add objects to the bin */
- gst_bin_add_many (GST_BIN (bin), queue, audioconvert,audioresample, sink, NULL);
-
- /* link the elements */
- gst_element_link_many (queue, audioconvert,audioresample, sink, NULL);
-
- /* Retrieve the sinkpad from the queue element and 'ghost' it onto
- * the bin so that the caller can find it generically */
- pad = gst_element_get_pad (queue, "sink");
- gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", pad));
- gst_object_unref (pad);
-
- //have_audio = TRUE;
-
- return GST_ELEMENT (bin);
-
- /* ERRORS */
-no_output:
- {
- //g_print ("Could not create either ffmpegcolorspace or autovideosink for output");
- return NULL;
- }
-}
-
-static void
-new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
- GstBin *top_pipeline)
-{
- GstPad *out_pad;
- GstElement *output = NULL;
- GstCaps *caps;
- GstStructure *s;
- const gchar *stream_type;
-
- /* Decide which output we are creating based on the stream contents */
- caps = gst_pad_get_caps (pad);
- if (caps == NULL) {
- //g_print ("Decodebin produced an unknown stream - ignoring\n");
- return;
- }
-
- s = gst_caps_get_structure (caps, 0);
- if(s == NULL)/* Caps on a pad should always have exactly one entry */
- return;
-
- stream_type = gst_structure_get_name (s);
-
- if (g_str_has_prefix (stream_type, "video/x-raw-")) {
- /* Is a new video stream */
- //g_print ("Encountered a new video stream\n");
- output = create_video_output ();
- }
- else if (g_str_has_prefix (stream_type, "audio/x-raw-")) {
- //g_print ("Encountered a new audio stream\n");
- output = create_audio_output ();
- }
- else {
- //g_print ("Found unknown stream of type %s - ignoring\n", stream_type);
- }
-
- /* If no renderer was created, ignore this stream */
- if (output == NULL)
- return;
-
- /* Add the output into our pipeline */
- gst_bin_add (top_pipeline, output);
-
- /* If we created a output pipeline, retrieve the sink pad from it */
- out_pad = gst_element_get_pad (output, "sink");
- g_return_if_fail (out_pad != NULL);
-
- /* Attempt to link the new pad to the output */
- if (gst_pad_link (pad, out_pad) != GST_PAD_LINK_OK) {
- //g_print ("Failed to add the rendering pipeline for this new data stream\n");
- gst_bin_remove (top_pipeline, output);
- gst_object_unref (out_pad);
- return;
- }
- gst_object_unref (out_pad);
-
- /* New output renderer is successfully linked in the pipeline.
- * Change its state to playing so it is ready to receive data */
- gst_element_set_state (output, GST_STATE_PLAYING);
-}
-
-static void
-print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
-{
- gint i, count;
-
- count = gst_tag_list_get_tag_size (list, tag);
-
- for (i = 0; i < count; i++) {
- gchar *str;
-
- if (gst_tag_get_type (tag) == G_TYPE_STRING) {
- if (!gst_tag_list_get_string_index (list, tag, i, &str))
- g_assert_not_reached ();
- } else {
- str =
- g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
- }
-
- if (i == 0) {
- //g_print (" %15s: %s\n", gst_tag_get_nick (tag), str);
- } else {
- //g_print (" : %s\n", str);
- }
-
- g_free (str);
- }
-}
-
-
-
-static gboolean
-bus_call (GstBus *bus,
- GstMessage *message,
- gpointer data)
-{
- switch (GST_MESSAGE_TYPE (message)){
- case GST_MESSAGE_EOS:
- gst_message_unref (message);
- gst_element_set_state (bin, GST_STATE_NULL);
- /* Unreffing the bin will clean up all its children too */
- gst_object_unref (bin);
- mCurrentState = NONE;
- break;
- case GST_MESSAGE_ERROR:{
- GError *gerror;
- gchar *debug;
-
- gst_message_parse_error (message, &gerror, &debug);
- gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
- gst_message_unref (message);
- g_error_free (gerror);
- g_free (debug);
- gst_element_set_state (bin, GST_STATE_NULL);
- /* Unreffing the bin will clean up all its children too */
- gst_object_unref (bin);
- mCurrentState = NONE;
- break;
- }
- case GST_MESSAGE_WARNING:{
- GError *gerror;
- gchar *debug;
-
- gst_message_parse_warning (message, &gerror, &debug);
- gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
- gst_message_unref (message);
- g_error_free (gerror);
- g_free (debug);
- break;
- }
- case GST_MESSAGE_TAG:
- {
- GstTagList *tags;
-
- gst_message_parse_tag (message, &tags);
- if (tags) {
- //g_print ("TAGS received from element \"%s\".\n",
- // GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
-
- gst_tag_list_foreach (tags, print_tag, NULL);
- gst_tag_list_free (tags);
- tags = NULL;
- }
- break;
- }
- default:
- gst_message_unref (message);
- break;
- }
- return TRUE;
-}
-
-
-
-//static void
-//event_loop (GstElement * pipe)
-//{
-// GstBus *bus;
-// GstMessage *message = NULL;
-//
-// bus = gst_element_get_bus (GST_ELEMENT (pipe));
-//
-// while (TRUE) {
-// message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
-//
-// g_assert (message != NULL);
-//
-// switch (message->type) {
-// case GST_MESSAGE_EOS:
-// gst_message_unref (message);
-// return;
-// case GST_MESSAGE_ERROR:{
-// GError *gerror;
-// gchar *debug;
-//
-// gst_message_parse_error (message, &gerror, &debug);
-// gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
-// gst_message_unref (message);
-// g_error_free (gerror);
-// g_free (debug);
-// return;
-// }
-// case GST_MESSAGE_WARNING:{
-// GError *gerror;
-// gchar *debug;
-//
-// gst_message_parse_warning (message, &gerror, &debug);
-// gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
-// gst_message_unref (message);
-// g_error_free (gerror);
-// g_free (debug);
-// break;
-// }
-// case GST_MESSAGE_TAG:
-// {
-// GstTagList *tags;
-//
-// gst_message_parse_tag (message, &tags);
-// if (tags) {
-// //g_print ("TAGS received from element \"%s\".\n",
-// GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
-//
-// gst_tag_list_foreach (tags, print_tag, NULL);
-// gst_tag_list_free (tags);
-// tags = NULL;
-// }
-// break;
-// }
-// default:
-// gst_message_unref (message);
-// break;
-// }
-// }
-//}
-
-int
-gst_play_file (const char* file)
-{
- GstElement *filesrc, *decodebin, *sink;
- GstCaps* caps;
- //int length = strlen( file );
- //gst_init (&argc, &argv);
-
- if (file == NULL) {
- //g_print ("file is not present");
- goto no_output;
- }
-
- //g_print ("Constructing pipeline\n");
-
- /* create a new bin to hold the elements */
- bin = gst_pipeline_new ("pipeline");
- if(!bin)
- goto no_output;
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- if(!filesrc)
- goto no_output;
-
- g_object_set (G_OBJECT (filesrc), "location", file, NULL);
-
- if( g_str_has_suffix (file, "raw") )
- {
- sink = gst_element_factory_make ("devsoundsink", "sink");
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
-
- gst_element_link_filtered (filesrc, sink, caps);
- }
- else if( g_str_has_suffix (file, "g711") )
- {
- sink = gst_element_factory_make ("devsoundsink", "sink");
- caps = gst_caps_new_simple ("audio/x-alaw",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
-
- gst_element_link_filtered (filesrc, sink, caps);
- }
- else if( g_str_has_suffix (file, "g729") )
- {
- sink = gst_element_factory_make ("devsoundsink", "sink");
- caps = gst_caps_new_simple ("audio/g729",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
-
- gst_element_link_filtered (filesrc, sink, caps);
- }
- else if( g_str_has_suffix (file, "ilbc") )
- {
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/ilbc",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
-
- gst_element_link_filtered (filesrc, sink, caps);
- }
- else if( g_str_has_suffix (file, "amr") )
- {
- sink = gst_element_factory_make ("devsoundsink", "sink");
- caps = gst_caps_new_simple ("audio/amr",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- gst_bin_add_many (GST_BIN (bin), filesrc, sink, NULL);
-
- //gst_element_link (source, sink);
- gst_element_link_filtered (filesrc, sink, caps);
- }
-
- else
- {
- /* Create the decodebin */
- decodebin = gst_element_factory_make ("decodebin", NULL);
- if (!decodebin) {
- //g_print ("could not find the \"decodebin\" element\n");
- return -1;
- }
-
- /* add objects to the main pipeline */
- gst_bin_add_many (GST_BIN (bin), filesrc, decodebin, NULL);
-
- /* link the elements. */
- gst_element_link_many (filesrc, decodebin, NULL);
-
- /* Connect to decodebin's 'new-decoded-pad' signal to detect when it produces
- * a new stream */
- g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad",
- G_CALLBACK (new_decoded_pad), bin);
- }
-
- gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
- //g_print ("Starting playback\n");
- /* start playing */
- gst_element_set_state (bin, GST_STATE_PLAYING);
- return 0;
-
-no_output:
- return -1;
-
-}
-
-
-int
-gst_record_file (int type)
-{
- GstElement *audiosrc, *filesink;
- char* carray = NULL;
- GstCaps* caps;
- //g_print ("Constructing pipeline\n");
-
- /* switch case for recording type*/
- switch( type )
- {
- case RECORD_RAW:
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- carray = "c:\\data\\sounds\\Digital\\record.raw";
- break;
-
- case RECORD_AMR:
- {
- return gst_record_amr();
- }
- break;
-
- case RECORD_G711:
-
- caps = gst_caps_new_simple ("audio/x-alaw",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- carray = "c:\\data\\sounds\\Digital\\record.g711";
- break;
-
- case RECORD_G729: //
-
- caps = gst_caps_new_simple ("audio/g729",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- carray = "c:\\data\\sounds\\Digital\\record.g729";
- break;
-
- case RECORD_ILBC: //
-
- caps = gst_caps_new_simple ("audio/ilbc",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- carray = "c:\\data\\sounds\\Digital\\record.ilbc";
- break;
- case RECORD_WAV:
- {
- return gst_record_wav();
- }
- break;
- case RECORD_AAC:
- {
- return gst_record_aac();
- }
- break;
- default:
- return -1;
- break;
- }
- /* create a new bin to hold the elements */
- bin = gst_pipeline_new ("pipeline");
- if(!bin)
- goto no_output;
-
- /* create a disk reader */
- audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
- if(!audiosrc)
- goto no_output;
-
- /* Create the decodebin */
- filesink = gst_element_factory_make ("filesink", NULL);
- if(!filesink)
- goto no_output;
-
- g_object_set (G_OBJECT (audiosrc),
- "blocksize", 1280,
- NULL);
-
- g_object_set (G_OBJECT (filesink), "location", carray,"buffer-size",1280, NULL);
-
- /* add objects to the main pipeline */
- gst_bin_add_many (GST_BIN (bin), audiosrc, filesink, NULL);
-
- /* link the elements. */
- gst_element_link_filtered (audiosrc, filesink, caps);
- //gst_element_link_many (audiosrc, filesink, NULL);
- gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
-
- //g_print ("Starting recoring\n");
- /* start playing */
- gst_element_set_state (bin, GST_STATE_PLAYING);
-
- /* Run event loop listening for bus messages until EOS or ERROR */
- //event_loop (bin);
-
-// //g_print ("Finished playback - stopping pipeline\n");
-//
-// /* stop the bin */
-// gst_element_set_state (bin, GST_STATE_NULL);
-//
-// /* Unreffing the bin will clean up all its children too */
-// gst_object_unref (bin);
-//
- return 0;
-no_output:
- return -1;
-
-}
-
-
-int
-gst_record_wav ()
-{
- GstElement *audiosrc, *filesink, *wavenc;
- char* carray = NULL;
- GstCaps* caps;
-
- //g_print ("Constructing pipeline\n");
-
- /* create a new bin to hold the elements */
- bin = gst_pipeline_new ("pipeline");
- if(!bin)
- goto no_output;
-
- /* create a disk reader */
- audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
- if(!audiosrc)
- goto no_output;
-
- /* Create the decodebin */
- filesink = gst_element_factory_make ("filesink", NULL);
- if(!filesink)
- goto no_output;
-
- wavenc = gst_element_factory_make ("wavenc", NULL);
- if(!wavenc)
- goto no_output;
-
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 16000,
- "channels", G_TYPE_INT, 1, NULL);
-
- carray = "c:\\data\\sounds\\Digital\\record.wav";
-
- g_object_set (G_OBJECT (audiosrc),
- "blocksize", 1280,
- NULL);
-
- g_object_set (G_OBJECT (filesink), "location", carray,"buffer-size",1280, NULL);
-
- /* add objects to the main pipeline */
- gst_bin_add_many (GST_BIN (bin), audiosrc,wavenc, filesink, NULL);
-
- /* link the elements. */
- gst_element_link_filtered (audiosrc, wavenc, caps);
- gst_element_link (wavenc, filesink);
- gst_bus_add_watch( gst_pipeline_get_bus (GST_PIPELINE (bin)), bus_call, NULL);
- //g_print ("Starting recoring\n");
- /* start playing */
- gst_element_set_state (bin, GST_STATE_PLAYING);
-
- return 0;
-
-no_output:
- return -1;
-}
-
-int gst_pause()
-{
- gst_element_set_state (bin, GST_STATE_PAUSED);
- return 0;
-}
-
-int gst_resume()
-{
- gst_element_set_state (bin, GST_STATE_PLAYING);
- return 0;
-}
-
-
-int gst_record_stop()
-{
- gst_element_send_event (bin, gst_event_new_eos ());
- //gst_element_set_state (bin, GST_STATE_NULL);
- return 0;
-}
-
-
-int gst_seek()
-{
-// need to implement..
-}
-
-int gst_get_events()
-{
- return g_main_context_iteration(NULL, FALSE);
- //return 0;
-}
-
-int gst_unref()
-{
- //g_print ("Finished playback - stopping pipeline\n");
- /* stop the bin */
- gst_element_set_state (bin, GST_STATE_NULL);
- /* Unreffing the bin will clean up all its children too */
- gst_object_unref (bin);
- return 0;
-}
-
-int gst_record_aac()
-{
- GstElement *audiosrc,*filesink,*aacenc, *mp4mux;
- GstBus *bus;
- GstPad *mp4sinkpad,*aacencsrcpad;
- char* carray = NULL;
- GstCaps* caps;
-
- /*create a pipeline*/
- bin = gst_pipeline_new ("pipeline");
- if(!bin)
- goto no_output;
- /* create a disk reader */
- audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
- if(!audiosrc)
- goto no_output;
-
- /* Create the decodebin */
- filesink = gst_element_factory_make ("filesink", NULL);
- if(!filesink)
- goto no_output;
- //setting num-buffers
- //g_object_set (G_OBJECT (audiosrc), "num-buffers", 5000 , NULL);
- g_object_set (G_OBJECT (audiosrc),
- "blocksize", 1280,
- NULL);
-
- aacenc = gst_element_factory_make("nokiaaacenc", "nokiaaacenc");
- if(!aacenc)
- goto no_output;
- mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
- if(!mp4mux)
- goto no_output;
- caps = gst_caps_new_simple("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- carray = "c:\\data\\sounds\\Digital\\record.mp4";
-
-
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
- bus = gst_pipeline_get_bus(GST_PIPELINE (bin));
-
- gst_bus_add_watch(bus, bus_call, NULL);
-
- gst_object_unref(bus);
-
-
- //add objects to the main pipeline
- gst_bin_add_many(GST_BIN (bin),audiosrc,aacenc,mp4mux,filesink, NULL);
-
- gst_element_link_filtered (audiosrc, aacenc, caps);
-
- mp4sinkpad = gst_element_get_request_pad( mp4mux, "audio_%d");
-
- aacencsrcpad = gst_element_get_pad( aacenc, "src");
- if (gst_pad_link (aacencsrcpad,mp4sinkpad) != GST_PAD_LINK_OK) {
-
- g_print("gst_pad_link (aacencsrcpad,mp4sinkpad) failed");
-
- return -1;
- }
- //gst_element_link (aacenc, filesink);
- gst_element_link (mp4mux, filesink);
-
- gst_caps_unref (caps);
-
-
- gst_element_set_state(bin, GST_STATE_PLAYING);
-
- return 0;
-no_output:
- return -1;
-}
-
-int gst_record_amr()
-{
- GstElement *audiosrc, *filesink, *amrmux;
- GstBus *bus;
- char* carray = NULL;
- GstCaps* caps;
- /* create a new bin to hold the elements */
- bin = gst_pipeline_new ("pipeline");
- if(!bin)
- goto no_output;
- //g_print ("pipeline created");
- audiosrc = gst_element_factory_make ("devsoundsrc", "audio_source");
- // encoder = gst_element_factory_make ("wavenc", NULL);
- if(!audiosrc)
- goto no_output;
-
- amrmux = gst_element_factory_make ("amrmux", "muxer");
- if(!amrmux)
- goto no_output;
-
- filesink = gst_element_factory_make("filesink", "filesink");
- if(!filesink)
- goto no_output;
-
- caps = gst_caps_new_simple ("audio/amr",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
- carray = "c:\\data\\sounds\\Digital\\record.amr";
-
- g_object_set (G_OBJECT (audiosrc),
- "blocksize", 1280,
- NULL);
-
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (bin));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (bin),audiosrc,amrmux,filesink , NULL);
- /* link the elements */
- gst_element_link_filtered (audiosrc, amrmux, caps);
-
- gst_element_link( amrmux, filesink );
-
- gst_element_set_state (bin, GST_STATE_PLAYING);
-
- return 0;
-no_output:
- return -1;
-
-}
--- a/QtGSTPlayer/record_play.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-
-#ifndef __HELP_FILE_H__
-#define __HELP_FILE_H__
-#include <glib.h>
-#include <stdio.h>
-
-enum
-{
- NONE,
- PLAYING,
- STOP,
- PAUSE,
- /*RESUME,
- RECORDING*/
-};
-
-enum
-{
- RECORD_NONE,
- RECORD_AMR,
- RECORD_WAV,
- RECORD_RAW,
- RECORD_G711,
- RECORD_G729,
- RECORD_ILBC,
- RECORD_AAC
-};
-
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-int gst_play_file( const char* file );
-
-int gst_record_file( int type );
-
-int gst_record_wav();
-
-int gst_pause();
-
-int gst_resume();
-
-int gst_record_stop();
-
-int gst_seek();
-
-int gst_unref();
-
-int gst_get_events();
-
-int gst_record_aac();
-
-int gst_record_amr();
-
-#ifdef __cplusplus
-}
-#endif
-#endif //__HELP_FILE_H__
-
Binary file QtGSTPlayer/settings.png has changed
--- a/QtGSTPlayer/views.cpp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-#include <hbmainwindow.h>
-#include <hbview.h>
-//#include <hbformview.h>
-
-#include "views.h"
-
-// Helper methods for retrieving the views used in this application
-namespace Views {
-
- // Store the mainwindow ptr here because we cannot call HbWidget::mainWindow() from these static functions.
- HbMainWindow *win;
-
-/*!
- Returns the pointer to folder view.
-*/
- HbView *folderView()
- {
- // 0 since folderView was added first to the main window
- return win->viewAt(0);
- }
-
-/*!
- Returns the pointer to settings view.
-*/
- /* HbFormView *settingsView()
- {
- // 1 since settingsView was the second view added
- return static_cast<HbFormView *>(win->viewAt(1));
- }
- */
-}
--- a/QtGSTPlayer/views.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-#ifndef VIEWS_H
-#define VIEWS_H
-
-class HbView;
-//class HbFormView;
-class HbMainWindow;
-
-namespace Views
-{
- extern HbMainWindow *win;
- HbView *folderView();
- //HbFormView *settingsView();
-}
-
-#endif // VIEWS_H
--- a/data/gst_dll_2001F41F.txt Fri May 28 18:11:17 2010 -0500
+++ b/data/gst_dll_2001F41F.txt Fri Jun 25 17:18:46 2010 -0500
@@ -7,7 +7,6 @@
libgstdecodebin2.dll
libgstdevsoundsink.dll
libgstdevsoundsrc.dll
-libgstapp.dll
libgstqueue2.dll
libgstadder.dll
libgsttypefindfunctions.dll
@@ -15,29 +14,13 @@
libgstwavparse.dll
libgstaudiotestsrc.dll
libgstautodetect.dll
-libgstmad.dll
-libgstvideorate.dll
-libgstvideoscale.dll
-libgstvideotestsrc.dll
-libgstavi.dll
-libgstffmpegcolorspace.dll
-libgstmpegstream.dll
-libgstmpeg2dec.dll
-libgstsdlvideosink.dll
-libgstauparse.dll
-libgstqtdemux.dll
+libgstsubparse.dll
+libgsttcp.dll
+libgstvolume.dll
+libgstplaybin.dll
+libgstgdp.dll
+libgstapp.dll
gstqtmux.dll
libgstnokiaaacenc.dll
-libgstlibgstqueue2.dll
-libgstjpeg.dll
-libgstplaybin.dll
-libgstgdp.dll
-libgstvolume.dll
-libgsttcp.dll
-libgstsubparse.dll
-libgstaudiofx.dll
-libgstmulaw.dll
-libgstalaw.dll
libgstamrmux.dll
-libgstmpegaudioparse.dll
-libgstnokiaaacdec.dll
+
--- a/gst_nokia_speech/bwins/libgstnokiaaacencu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-EXPORTS
- _GST_PLUGIN_DESC @ 1 NONAME
- gst_aac_enc_get_type @ 2 NONAME
-
--- a/gst_nokia_speech/config.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/* config.h. Generated by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* defined if cdda headers are in a cdda/ directory */
-/* #undef CDPARANOIA_HEADERS_IN_DIR */
-
-/* Default audio sink */
-#define DEFAULT_AUDIOSINK "autoaudiosink"
-
-/* Default audio source */
-#define DEFAULT_AUDIOSRC "alsasrc"
-
-/* Default video sink */
-#define DEFAULT_VIDEOSINK "autovideosink"
-
-/* Default video source */
-#define DEFAULT_VIDEOSRC "v4lsrc"
-
-/* Default visualizer */
-#define DEFAULT_VISUALIZER "goom"
-
-/* Define to 1 if translation of program messages to the user's native
- language is requested. */
-#ifdef __SYMBIAN32__
-#undef ENABLE_NLS
-#else
-#define ENABLE_NLS 1
-#endif
-
-
-/* gettext package name */
-#define GETTEXT_PACKAGE "gst-plugins-base-0.10"
-
-/* macro to use to show function name */
-#define GST_FUNCTION __PRETTY_FUNCTION__
-
-/* Defined if gcov is enabled to force a rebuild due to config.h changing */
-/* #undef GST_GCOV_ENABLED */
-
-/* Default errorlevel to use */
-#define GST_LEVEL_DEFAULT GST_LEVEL_NONE
-
-/* GStreamer license */
-#define GST_LICENSE "LGPL"
-
-/* package name in plugins */
-#define GST_PACKAGE_NAME "GStreamer Base Plug-ins source release"
-
-/* package origin */
-#define GST_PACKAGE_ORIGIN "Unknown package origin"
-
-/* support for features: gstalsa */
-#define HAVE_ALSA
-
-/* support for features: cdparanoia */
-/* #undef HAVE_CDPARANOIA */
-
-/* Define if the host CPU is an Alpha */
-/* #undef HAVE_CPU_ALPHA */
-
-/* Define if the host CPU is an ARM */
-/* #undef HAVE_CPU_ARM */
-#ifdef __SYMBIAN32__
-#define HAVE_CPU_ARM 1
-#endif
-
-/* Define if the host CPU is a CRIS */
-/* #undef HAVE_CPU_CRIS */
-
-/* Define if the host CPU is a CRISv32 */
-/* #undef HAVE_CPU_CRISV32 */
-
-/* Define if the host CPU is a HPPA */
-/* #undef HAVE_CPU_HPPA */
-
-/* Define if the host CPU is an x86 */
-#ifndef __SYMBIAN32__
-#define HAVE_CPU_I386 1
-#endif
-/* Define if the host CPU is a IA64 */
-/* #undef HAVE_CPU_IA64 */
-
-/* Define if the host CPU is a M68K */
-/* #undef HAVE_CPU_M68K */
-
-/* Define if the host CPU is a MIPS */
-/* #undef HAVE_CPU_MIPS */
-
-/* Define if the host CPU is a PowerPC */
-/* #undef HAVE_CPU_PPC */
-
-/* Define if the host CPU is a 64 bit PowerPC */
-/* #undef HAVE_CPU_PPC64 */
-
-/* Define if the host CPU is a S390 */
-/* #undef HAVE_CPU_S390 */
-
-/* Define if the host CPU is a SPARC */
-/* #undef HAVE_CPU_SPARC */
-
-/* Define if the host CPU is a x86_64 */
-/* #undef HAVE_CPU_X86_64 */
-
-/* Define if the GNU dcgettext() function is already present or preinstalled.
- */
-#define HAVE_DCGETTEXT 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* support for features: */
-#define HAVE_EXTERNAL
-
-/* FIONREAD ioctl found in sys/filio.h */
-/* #undef HAVE_FIONREAD_IN_SYS_FILIO */
-
-/* FIONREAD ioctl found in sys/ioclt.h */
-#define HAVE_FIONREAD_IN_SYS_IOCTL 1
-
-/* defined if the compiler implements __func__ */
-#define HAVE_FUNC 1
-
-/* defined if the compiler implements __FUNCTION__ */
-#define HAVE_FUNCTION 1
-
-/* Define if the GNU gettext() function is already present or preinstalled. */
-#define HAVE_GETTEXT 1
-
-/* support for features: gnomevfssrc */
-#define HAVE_GNOME_VFS
-
-/* support for features: v4lsrc v4lmjpegsrc v4lmjpegsink */
-#define HAVE_GST_V4L
-
-/* Define if you have the iconv() function. */
-/* #undef HAVE_ICONV */
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `asound' library (-lasound). */
-/* #undef HAVE_LIBASOUND */
-
-/* support for features: libvisual */
-/* #undef HAVE_LIBVISUAL */
-
-/* Define if you have C99's lrint function. */
-#define HAVE_LRINT 1
-
-/* Define if you have C99's lrintf function. */
-#define HAVE_LRINTF 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* support for features: oggdemux oggmux */
-#define HAVE_OGG
-
-/* support for features: pango */
-#define HAVE_PANGO
-
-/* defined if the compiler implements __PRETTY_FUNCTION__ */
-#define HAVE_PRETTY_FUNCTION 1
-
-/* Define if RDTSC is available */
-#define HAVE_RDTSC 1
-
-/* Define to 1 if you have the <regex.h> header file. */
-#define HAVE_REGEX_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* support for features: theoradec theoraenc */
-/* #undef HAVE_THEORA */
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define if valgrind should be used */
-#define HAVE_VALGRIND 1
-
-/* support for features: vorbisenc vorbisdec */
-#define HAVE_VORBIS
-
-/* defined if vorbis_synthesis_restart is present */
-#define HAVE_VORBIS_SYNTHESIS_RESTART 1
-
-/* support for features: ximagesink */
-#define HAVE_X
-
-/* support for features: xshm */
-#define HAVE_XSHM
-
-/* support for features: xvimagesink */
-#define HAVE_XVIDEO
-
-/* gettext locale dir */
-#define LOCALEDIR "/home/datha/gst-plugins-base-0.10.8/share/locale"
-
-/* Name of package */
-#define PACKAGE "gst-plugins-base"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "GStreamer nokia speech"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer nokia speech"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "gst_nokia_speech"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.0"
-
-/* directory where plugins are located */
-
-/* The size of a `char', as computed by sizeof. */
-/* #undef SIZEOF_CHAR */
-
-/* The size of a `int', as computed by sizeof. */
-/* #undef SIZEOF_INT */
-
-/* The size of a `long', as computed by sizeof. */
-/* #undef SIZEOF_LONG */
-
-/* The size of a `short', as computed by sizeof. */
-/* #undef SIZEOF_SHORT */
-
-/* The size of a `void*', as computed by sizeof. */
-/* #undef SIZEOF_VOIDP */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.10.0"
-
-/* Define to 1 if your processor stores words with the most significant byte
- first (like Motorola and SPARC, unlike Intel and VAX). */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define to 1 if the X Window System is missing or not being used. */
-/* #undef X_DISPLAY_MISSING */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
--- a/gst_nokia_speech/eabi/libgstnokiaaacencu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-EXPORTS
- _GST_PLUGIN_DESC @ 1 NONAME
- gst_aac_enc_get_type @ 2 NONAME
-
--- a/gst_nokia_speech/group/bld.inf Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-PRJ_PLATFORMS
-DEFAULT
-
-PRJ_EXPORTS
-
-PRJ_MMPFILES
-#ifndef WINSCW
-gstaacenc.mmp
-#endif
\ No newline at end of file
--- a/gst_nokia_speech/group/gstaacenc.mmp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-// Gstreamer.MMP
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-
-#include <platform_paths.hrh>
-
-TARGET libgstnokiaaacenc.dll
-TARGETTYPE DLL
-UID 0x20004c45 0x0FE80A1C
-
-#ifdef EKA2
-LANG SC
-CAPABILITY All -Tcb
-VENDORID VID_DEFAULT
-#endif
-
-#if !defined(__WINSCW__) && !defined(__WINS__)
-EpocAllowDllData
-#endif
-
-MACRO HAVE_CONFIG_H //RAW_FRAME_SIZE
-
-
-USERINCLUDE ..
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-OS_LAYER_GLIB_SYSTEMINCLUDE
-
-USERINCLUDE ../../include/gstreamer
-USERINCLUDE ../../include/gstreamer/gst
-USERINCLUDE ../../include/gstreamer/gst/base
-USERINCLUDE ../../include/gstreamer/gst/controller
-USERINCLUDE ../../include/gstreamer/gst/dataprotocol
-USERINCLUDE ../../include/gstreamer/gst/net
-USERINCLUDE ../../include/gstreamer/gst/audio
-USERINCLUDE ../../include/gstreamer/gst/cdda
-USERINCLUDE ../../include/gstreamer/gst/floatcast
-USERINCLUDE ../../include/gstreamer/gst/interfaces
-USERINCLUDE ../../include/gstreamer/gst/netbuffer
-USERINCLUDE ../../include/gstreamer/gst/riff
-USERINCLUDE ../../include/gstreamer/gst/rtp
-USERINCLUDE ../../include/gstreamer/gst/tag
-USERINCLUDE ../../include/gstreamer/gst/video
-SYSTEMINCLUDE /epoc32/include/internal
-SOURCEPATH ..
-SOURCE gstaacenc.c gstframedaudioenc.c
-LIBRARY euser.lib
-LIBRARY libc.lib
-LIBRARY libdl.lib
-LIBRARY libglib.lib
-LIBRARY libgmodule.lib
-
-LIBRARY libgobject.lib
-LIBRARY libgthread.lib
-LIBRARY libm.lib
-LIBRARY libz.lib
-LIBRARY libgstreamer.lib
-LIBRARY enhaacplusencoder.lib
-LIBRARY libgstbase.lib
-
-#ifdef WINSCW
-LIBRARY ewsd.lib //wsd solution
-#endif
-
-
-
-SMPSAFE
--- a/gst_nokia_speech/gstaacenc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,603 +0,0 @@
-/* GStreamer AAC encoder
- * Copyright 2009 Collabora Multimedia,
- * Copyright 2009 Nokia Corporation
- * @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
- *
- * 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.
- */
-
-/* TODO non-GPL license */
-
-/**
- * SECTION:element-nokiaaacenc
- * @seealso: nokiaaacdec
- *
- * nokiaaacenc encodes raw audio to AAC streams.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <string.h>
-
-#include "gstaacenc.h"
-
-GST_DEBUG_CATEGORY_STATIC (aac_enc);
-#define GST_CAT_DEFAULT aac_enc
-
-enum
-{
- AAC_PROFILE_AUTO = 0,
- AAC_PROFILE_LC = 2,
- AAC_PROFILE_HE = 5
-};
-
-#define GST_TYPE_AAC_ENC_PROFILE (gst_aac_enc_profile_get_type ())
-static GType
-gst_aac_enc_profile_get_type (void)
-{
- static GType gst_aac_enc_profile_type = 0;
-
- if (!gst_aac_enc_profile_type) {
- static GEnumValue gst_aac_enc_profile[] = {
- {AAC_PROFILE_AUTO, "Codec selects LC or HE", "AUTO"},
- {AAC_PROFILE_LC, "Low complexity profile", "LC"},
- {AAC_PROFILE_HE, "High Efficiency", "HE"},
- {0, NULL, NULL},
- };
-
- gst_aac_enc_profile_type = g_enum_register_static ("GstNokiaAacEncProfile",
- gst_aac_enc_profile);
- }
-
- return gst_aac_enc_profile_type;
-}
-
-#define GST_TYPE_AAC_ENC_OUTPUTFORMAT (gst_aac_enc_outputformat_get_type ())
-static GType
-gst_aac_enc_outputformat_get_type (void)
-{
- static GType gst_aac_enc_outputformat_type = 0;
-
- if (!gst_aac_enc_outputformat_type) {
- static GEnumValue gst_aac_enc_outputformat[] = {
- {RAW, "AAC Raw format", "RAW"},
- {USE_ADTS, "Audio Data Transport Stream format", "ADTS"},
- {USE_ADIF, "Audio Data Interchange Format", "ADIF"},
- {0, NULL, NULL},
- };
-
- gst_aac_enc_outputformat_type =
- g_enum_register_static ("GstNokiaAacEncOutputFormat",
- gst_aac_enc_outputformat);
- }
-
- return gst_aac_enc_outputformat_type;
-}
-
-enum
-{
- PROP_0,
- PROP_BITRATE,
- PROP_PROFILE,
- PROP_FORMAT
-};
-
-static GstStaticPadTemplate gst_aac_enc_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) BYTE_ORDER, "
- "signed = (bool) TRUE, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "rate = (int) [ 8000, 96000 ], channels = (int) [ 1, 2 ] ")
- );
-
-static GstStaticPadTemplate gst_aac_enc_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/mpeg, " "mpegversion = (int) 4, "
- "rate = (int) [ 8000, 96000 ], channels = (int) [ 1, 2 ] ")
- );
-
-static void gst_aac_enc_base_init (gpointer g_class);
-static void gst_aac_enc_class_init (GstAACEncClass * klass);
-static void gst_aac_enc_init (GstAACEnc * filter, GstAACEncClass * klass);
-
-static void gst_aac_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_aac_enc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static void gst_aac_enc_finalize (GObject * object);
-static void gst_aac_enc_reset (GstAACEnc * enc);
-static GstStateChangeReturn gst_aac_enc_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_aac_enc_chain (GstPad * pad, GstBuffer * buffer);
-
-GST_BOILERPLATE (GstNokiaAACEnc, gst_aac_enc, GstElement, GST_TYPE_ELEMENT);
-
-static void
-gst_aac_enc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details_simple (element_class,
- "Nokia AAC encoder", "Codec/Encoder/Audio",
- "Nokia AAC encoder",
- "MCC, Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_aac_enc_src_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_aac_enc_sink_template));
-}
-
-/* initialize the plugin's class */
-static void
-gst_aac_enc_class_init (GstAACEncClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- GST_DEBUG_CATEGORY_INIT (aac_enc, "nokiaaacenc", 0, "Nokia AAC encoder");
-
- gobject_class->set_property = gst_aac_enc_set_property;
- gobject_class->get_property = gst_aac_enc_get_property;
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_aac_enc_finalize);
-
- /* properties */
- g_object_class_install_property (gobject_class, PROP_BITRATE,
- g_param_spec_int ("bitrate", "Bitrate (bps)", "Bitrate in bits/sec",
- 8 * 1000, 320 * 1000, 128 * 1000,
- (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT)));
- g_object_class_install_property (gobject_class, PROP_PROFILE,
- g_param_spec_enum ("profile", "Profile",
- "MPEG/AAC encoding profile",
- GST_TYPE_AAC_ENC_PROFILE, AAC_PROFILE_LC,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (gobject_class, PROP_FORMAT,
- g_param_spec_enum ("output-format", "Output format",
- "Format of output frames",
- GST_TYPE_AAC_ENC_OUTPUTFORMAT, RAW,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_aac_enc_change_state);
-}
-
-static void
-gst_aac_enc_init (GstAACEnc * enc, GstAACEncClass * klass)
-{
- enc->sinkpad =
- gst_pad_new_from_static_template (&gst_aac_enc_sink_template, "sink");
- gst_pad_set_setcaps_function (enc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_aac_enc_sink_setcaps));
- gst_pad_set_chain_function (enc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_aac_enc_chain));
- gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
-
- enc->srcpad =
- gst_pad_new_from_static_template (&gst_aac_enc_src_template, "src");
- gst_pad_use_fixed_caps (enc->srcpad);
- gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
-
-#ifndef GST_DISABLE_GST_DEBUG
- gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), aac_enc);
-#else
- gst_framed_audio_enc_init (&enc->enc, GST_ELEMENT (enc), NULL);
-#endif
-
- gst_aac_enc_reset (enc);
-}
-
-static void
-gst_aac_enc_reset (GstAACEnc * enc)
-{
- gst_framed_audio_enc_reset (&enc->enc);
- if (enc->encoder)
- EnAACPlus_Enc_Delete (enc->encoder);
- enc->encoder = NULL;
- g_free (enc->buffer);
- enc->buffer = NULL;
-}
-
-static void
-gst_aac_enc_finalize (GObject * object)
-{
- GstAACEnc *enc = (GstAACEnc *) object;
-
- gst_framed_audio_enc_finalize (&enc->enc);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_aac_enc_setup_encoder (GstAACEnc * enc)
-{
- AACPLUS_ENC_CONFIG enc_params;
- AACPLUS_ENC_MODE mode;
- gint rate, channels;
- guint maxbitrate;
-
- rate = enc->rate;
- channels = enc->channels;
-
- /* only up to 2 channels supported */
- enc_params.sampleRate = rate;
- enc_params.bitRate = enc->bitrate;
- enc_params.nChannels = channels;
- enc_params.aac_tools = USE_ALL;
- enc_params.pcm_mode = 16;
- enc_params.format = enc->format;
-
- /* check, warn and correct if the max bitrate for the given samplerate is
- * exceeded. Maximum of 6144 bit for a channel */
- maxbitrate =
- (guint) (6144.0 * (gdouble) rate / (gdouble) 1024.0 + .5) * channels;
- if (enc_params.bitRate > maxbitrate) {
- GST_ELEMENT_INFO (enc, RESOURCE, SETTINGS, (NULL),
- ("bitrate %d exceeds maximum allowed bitrate of %d for samplerate %d "
- "and %d channels. Setting bitrate to %d",
- enc_params.bitRate, maxbitrate, rate, channels, maxbitrate));
- enc_params.bitRate = maxbitrate;
- }
-
- /* set up encoder */
- if (enc->encoder)
- EnAACPlus_Enc_Delete (enc->encoder);
-
- /* only these profiles are really known to and supported by codec */
- switch (enc->profile) {
- case AAC_PROFILE_LC:
- mode = MODE_AACLC;
- break;
- case AAC_PROFILE_HE:
- mode = MODE_EAACPLUS;
- break;
- case AAC_PROFILE_AUTO:
- mode = MODE_AUTO;
- break;
- default:
- mode = MODE_AACLC;
- g_assert_not_reached ();
- break;
- }
- enc->encoder = EnAACPlus_Enc_Create (&enc_params, mode);
-
- if (!enc->encoder)
- goto setup_failed;
-
- /* query and setup params,
- * also set up some buffers for fancy HE */
- EnAACPlus_Enc_GetSetParam (enc->encoder, &enc->info);
-
-#define DUMP_FIELD(f) \
- GST_DEBUG_OBJECT (enc, "encoder info: " G_STRINGIFY (f) " = %d", enc->info.f);
-
- DUMP_FIELD (InBufSize);
- DUMP_FIELD (OutBufSize);
- DUMP_FIELD (Frame_Size);
- DUMP_FIELD (writeOffset);
- DUMP_FIELD (InBufSize);
-
- enc->raw_frame_size = enc->info.Frame_Size;
- enc->codec_frame_size = enc->info.OutBufSize;
- enc->frame_duration =
- GST_FRAMES_TO_CLOCK_TIME (enc->raw_frame_size / enc->channels / 2,
- enc->rate);
-
- g_free (enc->buffer);
- /* safety margin */
- enc->buffer = g_malloc (enc->info.InBufSize * 2);
-
- return TRUE;
-
- /* ERRORS */
-setup_failed:
- {
- GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL));
- return FALSE;
- }
-}
-
-static gint
-gst_aac_enc_rate_idx (gint rate)
-{
- static int rates[] = {
- 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025,
- 8000, 7350
- };
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (rates); ++i)
- if (rates[i] == rate)
- return i;
-
- return 0xF;
-}
-
-static gboolean
-gst_aac_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstAACEnc *enc;
- gboolean ret = TRUE;
- GstStructure *s;
- GstBuffer *buf = NULL;
- gint rate, channels;
-
- enc = GST_AAC_ENC (GST_PAD_PARENT (pad));
-
- /* extract stream properties */
- s = gst_caps_get_structure (caps, 0);
-
- if (!s)
- goto refuse_caps;
-
- ret = gst_structure_get_int (s, "rate", &rate);
- ret &= gst_structure_get_int (s, "channels", &channels);
-
- if (!ret)
- goto refuse_caps;
-
- enc->rate = rate;
- enc->channels = channels;
-
- /* NOTE:
- * - codec only supports LC or HE (= LC + SBR etc)
- * - HE has (more) restrictive samplerate/channels/bitrate combination
- * - AUTO makes codec select between LC or HE (depending on settings)
- */
-
- gst_aac_enc_setup_encoder (enc);
- if (!enc->encoder)
- return FALSE;
-
- /* HE iff writeOffset <> 0 iff Frame_Size <> 1024 * 2 * channels */
- if (enc->info.writeOffset)
- rate /= 2;
-
- /* create codec_data if raw output */
- if (enc->format == RAW) {
- gint rate_idx;
- guint8 *data;
-
- buf = gst_buffer_new_and_alloc (5);
- data = GST_BUFFER_DATA (buf);
- rate_idx = gst_aac_enc_rate_idx (rate);
-
- GST_DEBUG_OBJECT (enc, "codec_data: profile=%d, sri=%d, channels=%d",
- enc->profile, rate_idx, enc->channels);
-
- /* always write LC profile, and use implicit signaling for HE SBR */
- data[0] = ((2 & 0x1F) << 3) | ((rate_idx & 0xE) >> 1);
- data[1] = ((rate_idx & 0x1) << 7);
- if (rate_idx != 0x0F) {
- data[1] |= ((channels & 0xF) << 3);
- GST_BUFFER_SIZE (buf) = 2;
- } else {
- gint srate;
-
- srate = rate << 7;
- data[1] |= ((srate >> 24) & 0xFF);
- data[2] = ((srate >> 16) & 0xFF);
- data[3] = ((srate >> 8) & 0xFF);
- data[4] = (srate & 0xFF);
- data[4] |= ((channels & 0xF) << 3);
- GST_BUFFER_SIZE (buf) = 5;
- }
- }
-
- /* fix some in src template */
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (enc->srcpad));
- gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate,
- "channels", G_TYPE_INT, channels, NULL);
- if (buf) {
- gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
- gst_buffer_unref (buf);
- }
- ret = gst_pad_set_caps (enc->srcpad, caps);
- gst_caps_unref (caps);
-
- return ret;
-
- /* ERRORS */
-refuse_caps:
- {
- GST_WARNING_OBJECT (enc, "refused caps %" GST_PTR_FORMAT, caps);
- return FALSE;
- }
-}
-
-static gint
-gst_aac_enc_get_data (GstElement * element, const guint8 * in, guint8 * out,
- GstDtxDecision * dtx)
-{
- GstAACEnc *enc;
- gint res;
- gint offset;
- UWord32 used, encoded;
- Word8 *inbuffer;
-
- enc = GST_AAC_ENC_CAST (element);
-
- offset = enc->info.writeOffset;
- if (offset) {
- memcpy (enc->buffer + offset, in, enc->raw_frame_size);
- inbuffer = (Word8 *) enc->buffer;
- } else {
- inbuffer = (Word8 *) in;
- }
-
- res = EnAACPlus_Enc_Encode (enc->encoder, &enc->info, inbuffer, &used,
- (UWord8 *) out, &encoded);
-
- if (offset) {
- memcpy (enc->buffer, enc->buffer + used, offset);
- }
-
- return res == 0 ? encoded : -1;
-}
-
-/* set parameters */
-#define AUDIO_SAMPLE_RATE ((GST_AAC_ENC (enc->element))->rate)
-#define RAW_FRAME_SIZE ((GST_AAC_ENC (enc->element))->raw_frame_size)
-/* safe maximum frame size */
-#define CODEC_FRAME_SIZE ((GST_AAC_ENC (enc->element))->codec_frame_size)
-/* do not set variable frame;
- * this will make every frame act as a silence frame and force output */
-/* #define CODEC_FRAME_VARIABLE 1 */
-#define FRAME_DURATION ((GST_AAC_ENC (enc->element))->frame_duration)
-#define codec_get_data(enc, in, out, dtx) \
- gst_aac_enc_get_data (enc, in, out, dtx)
-
-/* and include code */
-#include "gstframedaudioenc.c"
-
-static GstFlowReturn
-gst_aac_enc_chain (GstPad * pad, GstBuffer * buf)
-{
- GstAACEnc *enc;
-
- enc = GST_AAC_ENC (GST_PAD_PARENT (pad));
-
- if (G_UNLIKELY (enc->encoder == NULL))
- goto not_negotiated;
-
- return gst_framed_audio_enc_chain (&enc->enc, buf, enc->srcpad, &enc->cnpad);
-
- /* ERRORS */
-not_negotiated:
- {
- GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL),
- ("format wasn't negotiated before chain function"));
- gst_buffer_unref (buf);
- return GST_FLOW_NOT_NEGOTIATED;
- }
-}
-
-static void
-gst_aac_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAACEnc *enc;
-
- enc = GST_AAC_ENC (object);
-
- switch (prop_id) {
- case PROP_BITRATE:
- enc->bitrate = g_value_get_int (value);
- break;
- case PROP_PROFILE:
- enc->profile = g_value_get_enum (value);
- break;
- case PROP_FORMAT:
- enc->format = g_value_get_enum (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_aac_enc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAACEnc *enc;
-
- enc = GST_AAC_ENC (object);
-
- switch (prop_id) {
- case PROP_BITRATE:
- g_value_set_int (value, enc->bitrate);
- break;
- case PROP_PROFILE:
- g_value_set_enum (value, enc->profile);
- break;
- case PROP_FORMAT:
- g_value_set_enum (value, enc->format);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static GstStateChangeReturn
-gst_aac_enc_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstAACEnc *enc = GST_AAC_ENC (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- if (ret == GST_STATE_CHANGE_FAILURE)
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_aac_enc_reset (enc);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-
- if (!gst_element_register (plugin, "nokiaaacenc", GST_RANK_SECONDARY,
- GST_TYPE_AAC_ENC))
- return FALSE;
-
- return TRUE;
-}
-
-/* this is the structure that gst-register looks for
- * so keep the name plugin_desc, or you cannot get your plug-in registered */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "nokiaaacenc",
- "Nokia AAC MCC codec",
- plugin_init, VERSION, "Proprietary", "gst-nokia-speech", "")
-
-EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
- {
- return &gst_plugin_desc;
- }
-
--- a/gst_nokia_speech/gstaacenc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/* GStreamer AAC encoder
- * Copyright 2009 Collabora Multimedia,
- * Copyright 2009 Nokia Corporation
- * @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
- *
- * 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.
- */
-
-/* TODO non-GPL license */
-
-#ifndef __GST_AAC_ENC_H__
-#define __GST_AAC_ENC_H__
-
-#include <gst/gst.h>
-
-#include <eaacplus_api.h>
-
-#include "gstframedaudioenc.h"
-
-G_BEGIN_DECLS
-
-/* #define's don't like whitespacey bits */
-#define GST_TYPE_AAC_ENC \
- (gst_aac_enc_get_type())
-#define GST_AAC_ENC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AAC_ENC,GstAACEnc))
-#define GST_AAC_ENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AAC_ENC,GstAACEncClass))
-#define GST_IS_AAC_ENC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AAC_ENC))
-#define GST_IS_AAC_ENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AAC_ENC))
-#define GST_AAC_ENC_CAST(obj) ((GstAACEnc*)(obj))
-
-
-typedef struct _GstNokiaAACEnc GstNokiaAACEnc;
-typedef struct _GstNokiaAACEncClass GstNokiaAACEncClass;
-
-typedef GstNokiaAACEnc GstAACEnc;
-typedef GstNokiaAACEncClass GstAACEncClass;
-
-struct _GstNokiaAACEnc
-{
- GstElement element;
-
- GstPad *sinkpad, *srcpad, *cnpad;
-
- GstFramedAudioEnc enc;
- HANDLE_AACPLUS_ENC encoder;
- AACPLUS_ENC_INFO info;
-
- /* mode selection */
- GstClockTime frame_duration;
- gint raw_frame_size;
- gint codec_frame_size;
-
- /* optional helper (history) buffer */
- guint8 *buffer;
-
- /* stream description */
- gint rate;
- gint channels;
-
- /* properties */
- gint bitrate;
- guint profile;
- guint format;
-};
-
-struct _GstNokiaAACEncClass
-{
- GstElementClass parent_class;
-};
-
-GType gst_aac_enc_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_AAC_ENC_H__ */
--- a/gst_nokia_speech/gstframedaudioenc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-/* GStreamer Framed Audio Encoder
- * Copyright 2009 Collabora Ltd,
- * Copyright 2009 Nokia Corporation
- * @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
- *
- * 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 <gst/gst.h>
-#include <gst/audio/audio.h>
-#include <string.h>
-
-#include "gstframedaudioenc.h"
-
-/* generic part */
-#ifndef RAW_FRAME_SIZE
-
-/* this will reference caller's debug category;
- * there is a copy of this per plugin lib (= debug category) */
-GST_DEBUG_CATEGORY_STATIC (framedaudioenc_debug);
-#define GST_CAT_DEFAULT framedaudioenc_debug
-
-void
-gst_framed_audio_enc_reset (GstFramedAudioEnc * enc)
-{
- gst_adapter_clear (enc->adapter);
- enc->next_ts = GST_CLOCK_TIME_NONE;
-}
-
-/* installs @enc as element private for @element's pad,
- * and possibly some event and query handler.
- * if these need overriding, chain up to them
- * chain and setcaps still need to be set by @element */
-void
-gst_framed_audio_enc_init (GstFramedAudioEnc * enc, GstElement * element,
- GstDebugCategory * cat)
-{
- enc->element = element;
-#ifndef GST_DISABLE_GST_DEBUG
- framedaudioenc_debug = cat;
-#endif
-
- enc->adapter = gst_adapter_new ();
-
- /* hook some */
- enc->sinkpad = gst_element_get_pad (enc->element, "sink");
- g_assert (enc->sinkpad);
- gst_pad_set_element_private (enc->sinkpad, enc);
-
- /* watch downstream events */
- gst_pad_set_event_function (enc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_framed_audio_enc_sink_event));
-
- gst_framed_audio_enc_reset (enc);
-}
-
-void
-gst_framed_audio_enc_finalize (GstFramedAudioEnc * enc)
-{
- gst_object_unref (enc->adapter);
-
- gst_pad_set_element_private (enc->sinkpad, NULL);
- gst_object_unref (enc->sinkpad);
-}
-
-GstPad *
-gst_framed_audio_enc_request_new_pad (GstFramedAudioEnc * enc,
- GstPadTemplate * templ, const gchar * req_name, GstPad ** pad_p)
-{
- GstElement *element;
- GstPad *newpad;
- GstElementClass *klass;
- GstCaps *caps;
-
- g_return_val_if_fail (templ != NULL, NULL);
-
- element = enc->element;
- klass = GST_ELEMENT_GET_CLASS (element);
-
- if (templ != gst_element_class_get_pad_template (klass, "cn"))
- goto wrong_template;
-
- GST_DEBUG_OBJECT (enc->element, "adding cn pad");
- newpad = gst_pad_new_from_template (templ, "cn");
- /* set template caps */
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (newpad));
- gst_pad_set_caps (newpad, caps);
- gst_caps_unref (caps);
- gst_pad_use_fixed_caps (newpad);
- gst_pad_set_active (newpad, TRUE);
- /* only 1 pad by name can be added */
- if (gst_element_add_pad (element, newpad)) {
- GST_OBJECT_LOCK (element);
- gst_object_replace ((GstObject **) pad_p, GST_OBJECT_CAST (newpad));
- GST_OBJECT_UNLOCK (element);
- GST_DEBUG_OBJECT (enc->element, "cn pad added");
- } else {
- gst_object_unref (newpad);
- goto already_requested;
- }
-
- return newpad;
-
- /* ERRORS */
-wrong_template:
- {
- GST_ERROR_OBJECT (element, "not our template!");
- return NULL;
- }
-already_requested:
- {
- GST_ERROR_OBJECT (element, "only 1 instance of a pad can be requested");
- return NULL;
- }
-}
-
-void
-gst_framed_audio_enc_release_pad (GstFramedAudioEnc * enc, GstPad * pad,
- GstPad ** pad_p, void (disable_cn) (GstElement *))
-{
- GstElement *element = enc->element;
-
- GST_DEBUG_OBJECT (enc->element, "releasing cn pad");
-
- GST_OBJECT_LOCK (element);
- if (pad != *pad_p)
- goto wrong_pad;
- GST_OBJECT_UNLOCK (element);
-
- /* reconfigure encoder */
- disable_cn (element);
-
- if (gst_element_remove_pad (element, pad)) {
- GST_OBJECT_LOCK (element);
- gst_object_replace ((GstObject **) pad_p, NULL);
- GST_OBJECT_UNLOCK (element);
- GST_DEBUG_OBJECT (enc->element, "cn pad released");
- }
-
- /* ERRORS */
-wrong_pad:
- {
- GST_OBJECT_UNLOCK (element);
- GST_ERROR_OBJECT (element, "pad not requested; can not be released!");
- return;
- }
-}
-
-gboolean
-gst_framed_audio_enc_sink_event (GstPad * pad, GstEvent * event)
-{
- GstFramedAudioEnc *enc;
-
- enc = gst_pad_get_element_private (pad);
- g_return_val_if_fail (enc, FALSE);
-
- GST_LOG_OBJECT (enc->element, "received %s", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- /* fall-through */
- case GST_EVENT_EOS:
- gst_adapter_clear (enc->adapter);
- enc->next_ts = GST_CLOCK_TIME_NONE;
- break;
- default:
- break;
- }
-
- return gst_pad_event_default (pad, event);
-}
-
-#else
-/* included part */
-
-/* parameters:
- RAW_FRAME_SIZE
- CODEC_FRAME_SIZE
- FRAME_DURATION
- AUDIO_SAMPLE_RATE (optional)
- callback:
- codec_get_data(enc, in, out, dtx)
-
- If one does not mind a few cycles, include'ing can also be replaced by
- a regular include & call, at the expense of some additional parameters
- passed some way or another.
-*/
-
-#ifndef AUDIO_SAMPLE_RATE
-#define AUDIO_SAMPLE_RATE (8000)
-#endif
-
-/* quite some conditional stuff;
- * the (ugly?) cost of trying to stay inner loop optimal */
-
-static GstFlowReturn
-gst_framed_audio_enc_chain (GstFramedAudioEnc * enc, GstBuffer * buf,
- GstPad * srcpad, GstPad ** _cnpad)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *obuf = NULL;
-#ifdef CN_PAD
- GstBuffer *cnbuf = NULL;
- GstPad *cnpad = NULL;
-#endif
- gboolean discont = FALSE;
- const guint8 *data;
- guint8 *odata;
- gint av, flush, osize;
-
-#ifdef CN_PAD
- GST_OBJECT_LOCK (enc->element);
- if (_cnpad)
- cnpad = *_cnpad;
- if (cnpad)
- gst_object_ref (cnpad);
- GST_OBJECT_UNLOCK (enc->element);
-#endif
-
- if (G_LIKELY (buf)) {
- GST_LOG_OBJECT (enc->element, "input buffer of size %d with ts: %"
- GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
- discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT);
-
- /* reposition to the new buffer's timestamp,
- * while correcting for some minor left-over */
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- if (GST_CLOCK_TIME_IS_VALID (enc->next_ts)) {
- GstClockTimeDiff diff, limit;
- GstClockTime tleft;
-
- tleft = GST_FRAMES_TO_CLOCK_TIME
- (gst_adapter_available (enc->adapter) / 2, AUDIO_SAMPLE_RATE);
- diff =
- GST_CLOCK_DIFF (enc->next_ts + tleft, GST_BUFFER_TIMESTAMP (buf));
- limit = GST_SECOND / AUDIO_SAMPLE_RATE / 2;
- /* try for a perfect stream if possible, do not act on rounding errors */
- if (diff > limit || diff < -limit) {
- enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
- if (enc->next_ts > tleft)
- enc->next_ts -= tleft;
- GST_LOG_OBJECT (enc->element, "marking discont based on timestamps");
- discont = TRUE;
- }
- } else
- enc->next_ts = GST_BUFFER_TIMESTAMP (buf);
- }
-
- gst_adapter_push (enc->adapter, buf);
- buf = NULL;
- }
-
- av = gst_adapter_available (enc->adapter);
- if (G_UNLIKELY (av < RAW_FRAME_SIZE))
- goto done;
-
- data = gst_adapter_peek (enc->adapter, av);
- obuf = gst_buffer_new_and_alloc (av / RAW_FRAME_SIZE * CODEC_FRAME_SIZE);
- odata = GST_BUFFER_DATA (obuf);
- osize = 0;
- flush = 0;
-
- while (TRUE) {
- gint esize;
-#ifdef CN_PAD
- GstDtxDecision dtx;
-
- /* safe default to start with, should get set */
- dtx = GST_DTX_DECISION_VOICE;
- esize = codec_get_data (enc->element, data + flush, odata, &dtx);
-#else
- esize = codec_get_data (enc->element, data + flush, odata, NULL);
-#endif
-
- if (G_UNLIKELY (esize < 0))
- goto encode_failed;
-
-#ifdef CN_PAD
- /* cn in a separate stream */
- switch (dtx) {
- case GST_DTX_DECISION_VOICE:
-#endif
- flush += RAW_FRAME_SIZE;
- av -= RAW_FRAME_SIZE;
-
- odata += esize;
- osize += esize;
-#ifdef CN_PAD
- break;
- case GST_DTX_DECISION_SID_UPDATE:
- GST_LOG_OBJECT (enc->element, "dtx: SID_UPDATE %d", esize);
- /* if already data before, need to put SID data separately */
- if (G_UNLIKELY (osize)) {
- cnbuf = gst_buffer_new_and_alloc (esize);
- memcpy (GST_BUFFER_DATA (cnbuf), data + osize, esize);
- } else {
- cnbuf = obuf;
- obuf = NULL;
- }
- /* and send one or both */
- goto send;
- break;
- case GST_DTX_DECISION_SID_NONE:
- GST_LOG_OBJECT (enc->element, "dtx: SID_NONE %d", esize);
- /* maybe send preceding voice, if any */
- goto send;
- break;
- }
-#endif
-
-#ifdef CODEC_FRAME_VARIABLE
- /* flush output after insufficient data */
- if (av >= RAW_FRAME_SIZE)
- continue;
-#else
- /* ... or some reduced (e.g. silence) frame */
- if (esize >= CODEC_FRAME_SIZE && av >= RAW_FRAME_SIZE)
- continue;
-#endif
-
-#ifdef CN_PAD
- send:
-#endif
- /* maybe a silent discarded frame */
- if (G_LIKELY (osize)) {
- GST_BUFFER_SIZE (obuf) = osize;
- GST_BUFFER_DURATION (obuf)
- = FRAME_DURATION * (flush / RAW_FRAME_SIZE);
- GST_BUFFER_TIMESTAMP (obuf) = enc->next_ts;
- if (G_UNLIKELY (discont)) {
- GST_BUFFER_FLAG_SET (obuf, GST_BUFFER_FLAG_DISCONT);
- discont = FALSE;
- }
-
- GST_LOG_OBJECT (enc->element,
- "pushing buffer of size %d with ts: %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (obuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (obuf)));
- gst_buffer_set_caps (obuf, GST_PAD_CAPS (srcpad));
- ret = gst_pad_push (srcpad, obuf);
- obuf = NULL;
- } else {
- ret = GST_FLOW_OK;
- }
-
-#ifdef CN_PAD
- /* check for stuff to send on cn pad */
- if (cnbuf && cnpad) {
- /* only at most 1 SID update per buffer */
- GST_BUFFER_SIZE (cnbuf) = esize;
- GST_BUFFER_DURATION (cnbuf) = FRAME_DURATION;
- GST_BUFFER_TIMESTAMP (cnbuf) = enc->next_ts;
-
- GST_LOG_OBJECT (enc->element,
- "pushing cn buffer of size %d with ts: %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (cnbuf),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (cnbuf)));
- gst_buffer_set_caps (cnbuf, GST_PAD_CAPS (cnpad));
- if (G_LIKELY (ret == GST_FLOW_OK)) {
- ret = gst_pad_push (cnpad, cnbuf);
- /* cn pad may not be linked */
- if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED))
- ret = GST_FLOW_OK;
- } else
- gst_pad_push (cnpad, cnbuf);
- cnbuf = NULL;
- } else if (G_UNLIKELY (cnbuf)) {
- /* should not occur */
- gst_buffer_unref (cnbuf);
- cnbuf = NULL;
- }
-
- if (dtx != GST_DTX_DECISION_VOICE) {
- /* still need to count non-voice encoded frame */
- flush += RAW_FRAME_SIZE;
- av -= RAW_FRAME_SIZE;
- }
-#endif /* CN_PAD */
-
- /* remove used part */
- gst_adapter_flush (enc->adapter, flush);
- if (GST_CLOCK_TIME_IS_VALID (enc->next_ts))
- enc->next_ts += FRAME_DURATION * (flush / RAW_FRAME_SIZE);
-
- /* end if insufficient left or error */
- if (av < RAW_FRAME_SIZE || ret != GST_FLOW_OK)
- break;
-
- /* allocate new buffer */
- if (!obuf) {
- obuf = gst_buffer_new_and_alloc (av / RAW_FRAME_SIZE * CODEC_FRAME_SIZE);
- odata = GST_BUFFER_DATA (obuf);
- osize = 0;
- }
- /* and prepare to consume again */
- data = gst_adapter_peek (enc->adapter, av);
- flush = 0;
- }
-
- if (!av) {
- enc->next_ts = GST_CLOCK_TIME_NONE;
- }
-
-done:
-#ifdef CN_PAD
- GST_OBJECT_LOCK (enc->element);
- if (cnpad)
- gst_object_unref (cnpad);
- GST_OBJECT_UNLOCK (enc->element);
-#endif
-
- return ret;
-
- /* ERRORS */
-encode_failed:
- {
- GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), (NULL));
- ret = GST_FLOW_ERROR;
- gst_buffer_unref (obuf);
- goto done;
- }
-}
-#endif
--- a/gst_nokia_speech/gstframedaudioenc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/* GStreamer Framed Audio Encoder
- * Copyright 2009 Collabora Ltd,
- * Copyright 2009 Nokia Corporation
- * @author: Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
- *
- * 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 __GST_FRAMED_AUDIO_ENC_H__
-#define __GST_FRAMED_AUDIO_ENC_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstNokiaFramedAudioEnc GstNokiaFramedAudioEnc;
-typedef struct _GstNokiaFramedAudioEncClass GstNokiaFramedAudioEncClass;
-
-typedef GstNokiaFramedAudioEnc GstFramedAudioEnc;
-typedef GstNokiaFramedAudioEncClass GstFramedAudioEncClass;
-
-struct _GstNokiaFramedAudioEnc
-{
- /* helper for this element */
- GstElement *element;
-
- /* private stuff */
-
- /* pad with incoming data */
- GstPad *sinkpad;
-
- GstAdapter *adapter;
- GstClockTime next_ts;
-};
-
-typedef enum _GstDtxDecision {
- GST_DTX_DECISION_VOICE,
- GST_DTX_DECISION_SID_UPDATE,
- GST_DTX_DECISION_SID_NONE
-} GstDtxDecision;
-
-void gst_framed_audio_enc_init (GstFramedAudioEnc * enc, GstElement * element,
- GstDebugCategory * cat);
-void gst_framed_audio_enc_reset (GstFramedAudioEnc * enc);
-void gst_framed_audio_enc_finalize (GstFramedAudioEnc * enc);
-GstPad * gst_framed_audio_enc_request_new_pad (GstFramedAudioEnc * enc,
- GstPadTemplate * templ, const gchar * req_name, GstPad ** pad_p);
-void gst_framed_audio_enc_release_pad (GstFramedAudioEnc * enc, GstPad * pad,
- GstPad ** pad_p, void (disable_cn) (GstElement *));
-gboolean gst_framed_audio_enc_sink_event (GstPad * pad, GstEvent * event);
-
-G_END_DECLS
-
-#endif /* __GST_FRAMED_AUDIO_ENC_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsa.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,556 +0,0 @@
-/* Copyright (C) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "gstalsa.h"
-
-#include <gst/audio/multichannel.h>
-
-static GstCaps *
-gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params,
- GstCaps * in_caps)
-{
- GstCaps *caps;
- guint min, max;
- gint err, dir, min_rate, max_rate, i;
-
- GST_LOG_OBJECT (obj, "probing sample rates ...");
-
- if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0)
- goto min_rate_err;
-
- if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0)
- goto max_rate_err;
-
- min_rate = min;
- max_rate = max;
-
- if (min_rate < 4000)
- min_rate = 4000; /* random 'sensible minimum' */
-
- if (max_rate <= 0)
- max_rate = G_MAXINT; /* or maybe just use 192400 or so? */
- else if (max_rate > 0 && max_rate < 4000)
- max_rate = MAX (4000, min_rate);
-
- GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min);
- GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max);
-
- caps = gst_caps_make_writable (in_caps);
-
- for (i = 0; i < gst_caps_get_size (caps); ++i) {
- GstStructure *s;
-
- s = gst_caps_get_structure (caps, i);
- if (min_rate == max_rate) {
- gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL);
- } else {
- gst_structure_set (s, "rate", GST_TYPE_INT_RANGE,
- min_rate, max_rate, NULL);
- }
- }
-
- return caps;
-
- /* ERRORS */
-min_rate_err:
- {
- GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s",
- snd_strerror (err));
- gst_caps_unref (in_caps);
- return NULL;
- }
-max_rate_err:
- {
- GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s",
- snd_strerror (err));
- gst_caps_unref (in_caps);
- return NULL;
- }
-}
-
-static const struct
-{
- const int width;
- const int depth;
- const int sformat;
- const int uformat;
-} pcmformats[] = {
- {
- 8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, {
- 16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, {
- 32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, {
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) /* no endian-unspecific enum available */
- 24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, {
-#else
- 24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, {
-#endif
- 32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32}
-};
-
-static GstCaps *
-gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
- GstCaps * in_caps)
-{
- snd_pcm_format_mask_t *mask;
- GstStructure *s;
- GstCaps *caps;
- gint i;
-
- snd_pcm_format_mask_malloc (&mask);
- snd_pcm_hw_params_get_format_mask (hw_params, mask);
-
- caps = gst_caps_new_empty ();
-
- for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
- GstStructure *scopy;
- gint w, width = 0, depth = 0;
-
- s = gst_caps_get_structure (in_caps, i);
- if (!gst_structure_has_name (s, "audio/x-raw-int")) {
- GST_WARNING_OBJECT (obj, "skipping non-int format");
- continue;
- }
- if (!gst_structure_get_int (s, "width", &width) ||
- !gst_structure_get_int (s, "depth", &depth))
- continue;
- if (width == 0 || (width % 8) != 0)
- continue; /* Only full byte widths are valid */
- for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
- if (pcmformats[w].width == width && pcmformats[w].depth == depth)
- break;
- if (w == G_N_ELEMENTS (pcmformats))
- continue; /* Unknown format */
-
- if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
- snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
- /* template contains { true, false } or just one, leave it as it is */
- scopy = gst_structure_copy (s);
- } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
- scopy = gst_structure_copy (s);
- gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
- } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
- scopy = gst_structure_copy (s);
- gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
- } else {
- scopy = NULL;
- }
- if (scopy) {
- if (width > 8) {
- /* TODO: proper endianness detection, for now it's CPU endianness only */
- gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
- }
- gst_caps_append_structure (caps, scopy);
- }
- }
-
- snd_pcm_format_mask_free (mask);
- gst_caps_unref (in_caps);
- return caps;
-}
-
-/* we don't have channel mappings for more than this many channels */
-#define GST_ALSA_MAX_CHANNELS 8
-
-static GstStructure *
-get_channel_free_structure (const GstStructure * in_structure)
-{
- GstStructure *s = gst_structure_copy (in_structure);
-
- gst_structure_remove_field (s, "channels");
- return s;
-}
-
-static void
-caps_add_channel_configuration (GstCaps * caps,
- const GstStructure * in_structure, gint min_chans, gint max_chans)
-{
- GstAudioChannelPosition pos[8] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_LFE,
- GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
- GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
- };
- GstStructure *s = NULL;
- gint c;
-
- if (min_chans == max_chans && max_chans <= 2) {
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
- gst_caps_append_structure (caps, s);
- return;
- }
-
- g_assert (min_chans >= 1);
-
- /* mono and stereo don't need channel configurations */
- if (min_chans == 2) {
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
- gst_caps_append_structure (caps, s);
- } else if (min_chans == 1 && max_chans >= 2) {
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
- gst_caps_append_structure (caps, s);
- }
-
- /* don't know whether to use 2.1 or 3.0 here - but I suspect
- * alsa might work around that/fix it somehow. Can we tell alsa
- * what our channel layout is like? */
- if (max_chans >= 3 && min_chans <= 3) {
- GstAudioChannelPosition pos_21[3] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_LFE
- };
-
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
- gst_audio_set_channel_positions (s, pos_21);
- gst_caps_append_structure (caps, s);
- }
-
- /* everything else (4, 6, 8 channels) needs a channel layout */
- for (c = MAX (4, min_chans); c <= 8; c += 2) {
- if (max_chans >= c) {
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
- gst_audio_set_channel_positions (s, pos);
- gst_caps_append_structure (caps, s);
- }
- }
-
- for (c = MAX (9, min_chans); c <= max_chans; ++c) {
- GstAudioChannelPosition *ch_layout;
- guint i;
-
- ch_layout = g_new (GstAudioChannelPosition, c);
- for (i = 0; i < c; ++i) {
- ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
- }
- s = get_channel_free_structure (in_structure);
- gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
- gst_audio_set_channel_positions (s, ch_layout);
- gst_caps_append_structure (caps, s);
- g_free (ch_layout);
- }
-}
-
-static GstCaps *
-gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
- GstCaps * in_caps)
-{
- GstCaps *caps;
- guint min, max;
- gint min_chans, max_chans;
- gint err, i;
-
- GST_LOG_OBJECT (obj, "probing channels ...");
-
- if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
- goto min_chan_error;
-
- if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
- goto max_chan_error;
-
- /* note: the above functions may return (guint) -1 */
- min_chans = min;
- max_chans = max;
-
- if (min_chans < 0) {
- min_chans = 1;
- max_chans = GST_ALSA_MAX_CHANNELS;
- } else if (max_chans < 0) {
- max_chans = GST_ALSA_MAX_CHANNELS;
- }
-
- if (min_chans > max_chans) {
- gint temp;
-
- GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
- "please fix your soundcard drivers", min, max);
- temp = min_chans;
- min_chans = max_chans;
- max_chans = temp;
- }
-
- /* pro cards seem to return large numbers for min_channels */
- if (min_chans > GST_ALSA_MAX_CHANNELS) {
- GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
- if (max_chans < min_chans) {
- max_chans = min_chans;
- } else {
- /* only support [max_chans; max_chans] for these cards for now
- * to avoid inflating the source caps with loads of structures ... */
- min_chans = max_chans;
- }
- } else {
- min_chans = MAX (min_chans, 1);
- max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
- }
-
- GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
- GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
-
- caps = gst_caps_new_empty ();
-
- for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
- GstStructure *s;
- GType field_type;
- gint c_min = min_chans;
- gint c_max = max_chans;
-
- s = gst_caps_get_structure (in_caps, i);
- /* the template caps might limit the number of channels (like alsasrc),
- * in which case we don't want to return a superset, so hack around this
- * for the two common cases where the channels are either a fixed number
- * or a min/max range). Example: alsasrc template has channels = [1,2] and
- * the detection will claim to support 8 channels for device 'plughw:0' */
- field_type = gst_structure_get_field_type (s, "channels");
- if (field_type == G_TYPE_INT) {
- gst_structure_get_int (s, "channels", &c_min);
- gst_structure_get_int (s, "channels", &c_max);
- } else if (field_type == GST_TYPE_INT_RANGE) {
- const GValue *val;
-
- val = gst_structure_get_value (s, "channels");
- c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
- c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
- } else {
- c_min = min_chans;
- c_max = max_chans;
- }
-
- caps_add_channel_configuration (caps, s, c_min, c_max);
- }
-
- gst_caps_unref (in_caps);
-
- return caps;
-
- /* ERRORS */
-min_chan_error:
- {
- GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
- snd_strerror (err));
- return NULL;
- }
-max_chan_error:
- {
- GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
- snd_strerror (err));
- return NULL;
- }
-}
-
-snd_pcm_t *
-gst_alsa_open_iec958_pcm (GstObject * obj)
-{
- char *iec958_pcm_name = NULL;
- snd_pcm_t *pcm = NULL;
- int res;
- char devstr[256]; /* Storage for local 'default' device string */
-
- /*
- * Try and open our default iec958 device. Fall back to searching on card x
- * if this fails, which should only happen on older alsa setups
- */
-
- /* The string will be one of these:
- * SPDIF_CON: Non-audio flag not set:
- * spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2}
- * SPDIF_CON: Non-audio flag set:
- * spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2}
- */
- sprintf (devstr,
- "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}",
- IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
- IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
- 0, IEC958_AES3_CON_FS_48000);
-
- GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr);
- iec958_pcm_name = devstr;
-
- res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
- if (G_UNLIKELY (res < 0)) {
- GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s",
- snd_strerror (res));
- pcm = NULL;
- }
-
- return pcm;
-}
-
-
-/*
- * gst_alsa_probe_supported_formats:
- *
- * Takes the template caps and returns the subset which is actually
- * supported by this device.
- *
- */
-
-GstCaps *
-gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle,
- const GstCaps * template_caps)
-{
- snd_pcm_hw_params_t *hw_params;
- snd_pcm_stream_t stream_type;
- GstCaps *caps;
- gint err;
-
- snd_pcm_hw_params_malloc (&hw_params);
- if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0)
- goto error;
-
- stream_type = snd_pcm_stream (handle);
-
- caps = gst_caps_copy (template_caps);
-
- if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps)))
- goto subroutine_error;
-
- if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps)))
- goto subroutine_error;
-
- if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps)))
- goto subroutine_error;
-
- /* Try opening IEC958 device to see if we can support that format (playback
- * only for now but we could add SPDIF capture later) */
- if (stream_type == SND_PCM_STREAM_PLAYBACK) {
- snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj);
-
- if (G_LIKELY (pcm)) {
- gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL));
- snd_pcm_close (pcm);
- }
- }
-
- snd_pcm_hw_params_free (hw_params);
- return caps;
-
- /* ERRORS */
-error:
- {
- GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err));
- snd_pcm_hw_params_free (hw_params);
- return NULL;
- }
-subroutine_error:
- {
- GST_ERROR_OBJECT (obj, "failed to query formats");
- snd_pcm_hw_params_free (hw_params);
- return NULL;
- }
-}
-
-static gchar *
-gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard,
- gint device_num, snd_pcm_stream_t stream)
-{
- snd_ctl_card_info_t *info = NULL;
- snd_ctl_t *ctl = NULL;
- gchar *ret = NULL;
- gint dev = -1;
-
- GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num);
-
- if (snd_ctl_open (&ctl, devcard, 0) < 0)
- return NULL;
-
- snd_ctl_card_info_malloc (&info);
- if (snd_ctl_card_info (ctl, info) < 0)
- goto done;
-
- while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) {
- if (dev == device_num) {
- snd_pcm_info_t *pcminfo;
-
- snd_pcm_info_malloc (&pcminfo);
- snd_pcm_info_set_device (pcminfo, dev);
- snd_pcm_info_set_subdevice (pcminfo, 0);
- snd_pcm_info_set_stream (pcminfo, stream);
- if (snd_ctl_pcm_info (ctl, pcminfo) < 0) {
- snd_pcm_info_free (pcminfo);
- break;
- }
-
- ret = g_strdup (snd_pcm_info_get_name (pcminfo));
- snd_pcm_info_free (pcminfo);
- GST_LOG_OBJECT (obj, "name from pcminfo: %s", GST_STR_NULL (ret));
- }
- }
-
- if (ret == NULL) {
- char *name = NULL;
- gint card;
-
- GST_LOG_OBJECT (obj, "no luck so far, trying backup");
- card = snd_ctl_card_info_get_card (info);
- snd_card_get_name (card, &name);
- ret = g_strdup (name);
- free (name);
- }
-
-done:
- snd_ctl_card_info_free (info);
- snd_ctl_close (ctl);
-
- return ret;
-}
-
-gchar *
-gst_alsa_find_device_name (GstObject * obj, const gchar * device,
- snd_pcm_t * handle, snd_pcm_stream_t stream)
-{
- gchar *ret = NULL;
-
- if (device != NULL) {
- gchar *dev, *comma;
- gint devnum;
-
- GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device);
-
- /* only want name:card bit, but not devices and subdevices */
- dev = g_strdup (device);
- if ((comma = strchr (dev, ','))) {
- *comma = '\0';
- devnum = atoi (comma + 1);
- ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream);
- }
- g_free (dev);
- }
-
- if (ret == NULL && handle != NULL) {
- snd_pcm_info_t *info;
-
- GST_LOG_OBJECT (obj, "Trying to get device name from open handle");
- snd_pcm_info_malloc (&info);
- snd_pcm_info (handle, info);
- ret = g_strdup (snd_pcm_info_get_name (info));
- snd_pcm_info_free (info);
- }
-
- GST_LOG_OBJECT (obj, "Device name for device '%s': %s",
- GST_STR_NULL (device), GST_STR_NULL (ret));
-
- return ret;
-}
--- a/gst_plugins_base/ext/alsa/gstalsa.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_H__
-#define __GST_ALSA_H__
-
-
-#define ALSA_PCM_NEW_HW_PARAMS_API
-#define ALSA_PCM_NEW_SW_PARAMS_API
-
-#include <alsa/asoundlib.h>
-#include <alsa/control.h>
-#include <alsa/error.h>
-#include <gst/gst.h>
-
-#define GST_CHECK_ALSA_VERSION(major,minor,micro) \
- (SND_LIB_MAJOR > (major) || \
- (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \
- (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \
- SND_LIB_SUBMINOR >= (micro)))
-
-GST_DEBUG_CATEGORY_EXTERN (alsa_debug);
-#define GST_CAT_DEFAULT alsa_debug
-
-snd_pcm_t * gst_alsa_open_iec958_pcm (GstObject * obj);
-
-GstCaps * gst_alsa_probe_supported_formats (GstObject * obj,
- snd_pcm_t * handle,
- const GstCaps * template_caps);
-
-gchar * gst_alsa_find_device_name (GstObject * obj,
- const gchar * device,
- snd_pcm_t * handle,
- snd_pcm_stream_t stream);
-
-#endif /* __GST_ALSA_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsadeviceprobe.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/* Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- * Copyright (C) 2005 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsadeviceprobe.h"
-#include "gst/interfaces/propertyprobe.h"
-
-static const GList *
-gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe)
-{
- GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
- static GList *list = NULL;
-
- /* well, not perfect, but better than no locking at all.
- * In the worst case we leak a list node, so who cares? */
- GST_CLASS_LOCK (GST_OBJECT_CLASS (klass));
-
- if (!list) {
- GParamSpec *pspec;
-
- pspec = g_object_class_find_property (klass, "device");
- list = g_list_append (NULL, pspec);
- }
-
- GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass));
-
- return list;
-}
-
-static GList *
-gst_alsa_get_device_list (snd_pcm_stream_t stream)
-{
- snd_ctl_t *handle;
- int card, err, dev;
- snd_ctl_card_info_t *info;
- snd_pcm_info_t *pcminfo;
- gboolean mixer = (stream == -1);
- GList *list = NULL;
-
- if (stream == -1)
- stream = 0;
-
- snd_ctl_card_info_malloc (&info);
- snd_pcm_info_malloc (&pcminfo);
- card = -1;
-
- if (snd_card_next (&card) < 0 || card < 0) {
- /* no soundcard found */
- return NULL;
- }
-
- while (card >= 0) {
- gchar name[32];
-
- g_snprintf (name, sizeof (name), "hw:%d", card);
- if ((err = snd_ctl_open (&handle, name, 0)) < 0) {
- goto next_card;
- }
- if ((err = snd_ctl_card_info (handle, info)) < 0) {
- snd_ctl_close (handle);
- goto next_card;
- }
-
- if (mixer) {
- list = g_list_append (list, g_strdup (name));
- } else {
- dev = -1;
- while (1) {
- gchar *gst_device;
-
- snd_ctl_pcm_next_device (handle, &dev);
-
- if (dev < 0)
- break;
- snd_pcm_info_set_device (pcminfo, dev);
- snd_pcm_info_set_subdevice (pcminfo, 0);
- snd_pcm_info_set_stream (pcminfo, stream);
- if ((err = snd_ctl_pcm_info (handle, pcminfo)) < 0) {
- continue;
- }
-
- gst_device = g_strdup_printf ("hw:%d,%d", card, dev);
- list = g_list_append (list, gst_device);
- }
- }
- snd_ctl_close (handle);
- next_card:
- if (snd_card_next (&card) < 0) {
- break;
- }
- }
-
- snd_ctl_card_info_free (info);
- snd_pcm_info_free (pcminfo);
-
- return list;
-}
-
-static void
-gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- if (!g_str_equal (pspec->name, "device")) {
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- }
-}
-
-static gboolean
-gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- /* don't cache probed data */
- return TRUE;
-}
-
-static GValueArray *
-gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstElementClass *klass;
- const GList *templates;
- snd_pcm_stream_t mode = -1;
- GValueArray *array;
- GValue value = { 0, };
- GList *l, *list;
-
- if (!g_str_equal (pspec->name, "device")) {
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- return NULL;
- }
-
- klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));
-
- /* I'm pretty sure ALSA has a good way to do this. However, their cool
- * auto-generated documentation is pretty much useless if you try to
- * do function-wise look-ups. */
- /* we assume one pad template at max [zero=mixer] */
- templates = gst_element_class_get_pad_template_list (klass);
- if (templates) {
- if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
- mode = SND_PCM_STREAM_CAPTURE;
- else
- mode = SND_PCM_STREAM_PLAYBACK;
- }
-
- list = gst_alsa_get_device_list (mode);
-
- if (list == NULL) {
- GST_LOG_OBJECT (probe, "No devices found");
- return NULL;
- }
-
- array = g_value_array_new (g_list_length (list));
- g_value_init (&value, G_TYPE_STRING);
- for (l = list; l != NULL; l = l->next) {
- GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
- g_value_take_string (&value, (gchar *) l->data);
- l->data = NULL;
- g_value_array_append (array, &value);
- }
- g_value_unset (&value);
- g_list_free (list);
-
- return array;
-}
-
-static void
-gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface)
-{
- iface->get_properties = gst_alsa_device_property_probe_get_properties;
- iface->probe_property = gst_alsa_device_property_probe_probe_property;
- iface->needs_probe = gst_alsa_device_property_probe_needs_probe;
- iface->get_values = gst_alsa_device_property_probe_get_values;
-}
-
-void
-gst_alsa_type_add_device_property_probe_interface (GType type)
-{
- static const GInterfaceInfo probe_iface_info = {
- (GInterfaceInitFunc) gst_alsa_property_probe_interface_init,
- NULL,
- NULL,
- };
-
- g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
- &probe_iface_info);
-}
--- a/gst_plugins_base/ext/alsa/gstalsadeviceprobe.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/* Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __GST_ALSA_DEVICE_PROBE_H__
-#define __GST_ALSA_DEVICE_PROBE_H__
-
-#include "gstalsa.h"
-
-G_BEGIN_DECLS
-
-void gst_alsa_type_add_device_property_probe_interface (GType type);
-
-G_END_DECLS
-
-#endif /* __GST_ALSA_DEVICE_PROBE_H__ */
-
--- a/gst_plugins_base/ext/alsa/gstalsamixer.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,887 +0,0 @@
-/* ALSA mixer implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-alsamixer
- * @short_description: control properties of an audio device
- * @see_also: alsasink, alsasrc
- *
- * <refsect2>
- * <para>
- * This element controls various aspects such as the volume and balance
- * of an audio device using the ALSA api.
- * </para>
- * <para>
- * The application should query and use the interfaces provided by this
- * element to control the device.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixer.h"
-
-static void gst_alsa_mixer_update_option (GstAlsaMixer * mixer,
- GstAlsaMixerOptions * alsa_opts);
-static void gst_alsa_mixer_update_track (GstAlsaMixer * mixer,
- GstAlsaMixerTrack * alsa_track);
-static int gst_alsa_mixer_handle_callback (snd_mixer_t * handle,
- unsigned int mask, snd_mixer_elem_t * elem);
-
-/* First some utils, then the mixer implementation */
-static gboolean
-gst_alsa_mixer_open (GstAlsaMixer * mixer)
-{
- gint err;
- snd_ctl_t *ctl;
- snd_ctl_card_info_t *card_info;
-
- g_return_val_if_fail (mixer->handle == NULL, FALSE);
-
- /* open and initialize the mixer device */
- err = snd_mixer_open (&mixer->handle, 0);
- if (err < 0 || mixer->handle == NULL)
- goto open_failed;
-
- if ((err = snd_mixer_attach (mixer->handle, mixer->device)) < 0) {
- GST_WARNING ("Cannot open mixer for sound device '%s': %s", mixer->device,
- snd_strerror (err));
- goto error;
- }
-
- if ((err = snd_mixer_selem_register (mixer->handle, NULL, NULL)) < 0) {
- GST_WARNING ("Cannot register mixer elements: %s", snd_strerror (err));
- goto error;
- }
-
- if ((err = snd_mixer_load (mixer->handle)) < 0) {
- GST_WARNING ("Cannot load mixer settings: %s", snd_strerror (err));
- goto error;
- }
-
- snd_mixer_set_callback_private (mixer->handle, mixer);
- snd_mixer_set_callback (mixer->handle, gst_alsa_mixer_handle_callback);
-
- /* now get the device name, any of this is not fatal */
- g_free (mixer->cardname);
- if ((err = snd_ctl_open (&ctl, mixer->device, 0)) < 0) {
- GST_WARNING ("Cannot open CTL: %s", snd_strerror (err));
- goto no_card_name;
- }
-
- snd_ctl_card_info_malloc (&card_info);
- if ((err = snd_ctl_card_info (ctl, card_info)) < 0) {
- GST_WARNING ("Cannot get card info: %s", snd_strerror (err));
- snd_ctl_close (ctl);
- goto no_card_name;
- }
-
- mixer->cardname = g_strdup (snd_ctl_card_info_get_name (card_info));
- GST_DEBUG ("Card name = %s", GST_STR_NULL (mixer->cardname));
- snd_ctl_card_info_free (card_info);
- snd_ctl_close (ctl);
-
-no_card_name:
- if (mixer->cardname == NULL) {
- mixer->cardname = g_strdup ("Unknown");
- GST_DEBUG ("Cannot find card name");
- }
-
- GST_INFO ("Successfully opened mixer for device '%s'.", mixer->device);
-
- return TRUE;
-
- /* ERROR */
-open_failed:
- {
- GST_WARNING ("Cannot open mixer: %s", snd_strerror (err));
- mixer->handle = NULL;
- return FALSE;
- }
-error:
- {
- snd_mixer_close (mixer->handle);
- mixer->handle = NULL;
- return FALSE;
- }
-}
-
-static snd_mixer_elem_t *
-gst_alsa_mixer_find_master_mixer (GstAlsaMixer * mixer, snd_mixer_t * handle)
-{
- snd_mixer_elem_t *element;
- gint i, count;
-
- count = snd_mixer_get_count (handle);
-
- /* Check if we have a playback mixer labelled as 'Master' */
- element = snd_mixer_first_elem (handle);
- for (i = 0; i < count; i++) {
- if (snd_mixer_selem_has_playback_volume (element) &&
- strcmp (snd_mixer_selem_get_name (element), "Master") == 0) {
- return element;
- }
- element = snd_mixer_elem_next (element);
- }
-
- /* If not, check if we have a playback mixer labelled as 'Front' */
- element = snd_mixer_first_elem (handle);
- for (i = 0; i < count; i++) {
- if (snd_mixer_selem_has_playback_volume (element) &&
- strcmp (snd_mixer_selem_get_name (element), "Front") == 0) {
- return element;
- }
- element = snd_mixer_elem_next (element);
- }
-
- /* If not, check if we have a playback mixer labelled as 'PCM' */
- element = snd_mixer_first_elem (handle);
- for (i = 0; i < count; i++) {
- if (snd_mixer_selem_has_playback_volume (element) &&
- strcmp (snd_mixer_selem_get_name (element), "PCM") == 0) {
- return element;
- }
- element = snd_mixer_elem_next (element);
- }
-
- /* If not, check if we have a playback mixer with both volume and switch */
- element = snd_mixer_first_elem (handle);
- for (i = 0; i < count; i++) {
- if (snd_mixer_selem_has_playback_volume (element) &&
- snd_mixer_selem_has_playback_switch (element)) {
- return element;
- }
- element = snd_mixer_elem_next (element);
- }
-
- /* If not, take any playback mixer with a volume control */
- element = snd_mixer_first_elem (handle);
- for (i = 0; i < count; i++) {
- if (snd_mixer_selem_has_playback_volume (element)) {
- return element;
- }
- element = snd_mixer_elem_next (element);
- }
-
- /* Looks like we're out of luck ... */
- return NULL;
-}
-
-static void
-gst_alsa_mixer_update (GstAlsaMixer * mixer, snd_mixer_elem_t * elem)
-{
- GList *item;
-
- g_return_if_fail (mixer != NULL);
-
- g_static_rec_mutex_lock (mixer->rec_mutex);
-
- for (item = mixer->tracklist; item != NULL; item = item->next) {
- if (GST_IS_ALSA_MIXER_TRACK (item->data)) {
- if (elem && (GST_ALSA_MIXER_TRACK (item->data)->element != elem))
- continue;
-
- gst_alsa_mixer_update_track (mixer, GST_ALSA_MIXER_TRACK (item->data));
- } else if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) {
- if (elem && (GST_ALSA_MIXER_OPTIONS (item->data)->element != elem))
- continue;
-
- gst_alsa_mixer_update_option (mixer, GST_ALSA_MIXER_OPTIONS (item->data));
- }
- }
-
- g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-static int
-gst_alsa_mixer_elem_handle_callback (snd_mixer_elem_t * elem, unsigned int mask)
-{
- GstAlsaMixer *mixer =
- (GstAlsaMixer *) snd_mixer_elem_get_callback_private (elem);
-
- GST_LOG ("ALSA elem cb");
-
- g_return_val_if_fail (mixer != NULL, 1);
-
- gst_alsa_mixer_update (mixer, elem);
-
- return 0;
-}
-
-static int
-gst_alsa_mixer_handle_callback (snd_mixer_t * handle, unsigned int mask,
- snd_mixer_elem_t * elem)
-{
- GstAlsaMixer *mixer =
- (GstAlsaMixer *) snd_mixer_get_callback_private (handle);
-
- GST_LOG ("ALSA cb");
-
- g_return_val_if_fail (mixer != NULL, 1);
-
- /* Hopefully won't be call recursively and will handle pending elem events */
- snd_mixer_handle_events (mixer->handle);
-
- gst_alsa_mixer_update (mixer, elem);
-
- return 0;
-}
-
-static void
-gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer)
-{
- gint i, count;
- snd_mixer_elem_t *element, *master;
- GList *item;
-
- g_return_if_fail (mixer->handle != NULL);
-
- if (mixer->tracklist)
- return;
-
- g_static_rec_mutex_lock (mixer->rec_mutex);
-
- master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle);
-
- count = snd_mixer_get_count (mixer->handle);
- element = snd_mixer_first_elem (mixer->handle);
-
- /* build track list
- *
- * Some ALSA tracks may have playback and capture capabilities.
- * Here we model them as two separate GStreamer tracks.
- */
-
- for (i = 0; i < count; i++) {
- GstMixerTrack *play_track = NULL;
- GstMixerTrack *cap_track = NULL;
- const gchar *name;
- GList *item;
- gint samename = 0;
-
- name = snd_mixer_selem_get_name (element);
-
- /* prevent dup names */
- for (item = mixer->tracklist; item != NULL; item = item->next) {
- snd_mixer_elem_t *temp;
-
- if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
- temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
- else
- temp = GST_ALSA_MIXER_TRACK (item->data)->element;
-
- if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0)
- samename++;
- }
-
- GST_LOG ("[%s] probing element #%u, mixer->dir=%u", name, i, mixer->dir);
-
- if (mixer->dir & GST_ALSA_MIXER_PLAYBACK) {
- gboolean has_playback_switch, has_playback_volume;
-
- has_playback_switch = snd_mixer_selem_has_playback_switch (element);
- has_playback_volume = snd_mixer_selem_has_playback_volume (element);
-
- GST_LOG ("[%s] PLAYBACK: has_playback_volume=%d, has_playback_switch=%d"
- "%s", name, has_playback_volume, has_playback_switch,
- (element == master) ? " MASTER" : "");
-
- if (has_playback_volume) {
- gint flags = GST_MIXER_TRACK_OUTPUT;
-
- if (element == master)
- flags |= GST_MIXER_TRACK_MASTER;
-
- play_track = gst_alsa_mixer_track_new (element, samename, i,
- flags, FALSE, NULL, FALSE);
-
- } else if (has_playback_switch) {
- /* simple mute switch */
- play_track = gst_alsa_mixer_track_new (element, samename, i,
- GST_MIXER_TRACK_OUTPUT, TRUE, NULL, FALSE);
- }
-
- if (snd_mixer_selem_is_enumerated (element)) {
- GstMixerOptions *opts = gst_alsa_mixer_options_new (element, i);
-
- GST_LOG ("[%s] is enumerated (%d)", name, i);
- mixer->tracklist = g_list_append (mixer->tracklist, opts);
- }
- }
-
- if (mixer->dir & GST_ALSA_MIXER_CAPTURE) {
- gboolean has_capture_switch, has_common_switch;
- gboolean has_capture_volume, has_common_volume;
-
- has_capture_switch = snd_mixer_selem_has_capture_switch (element);
- has_common_switch = snd_mixer_selem_has_common_switch (element);
- has_capture_volume = snd_mixer_selem_has_capture_volume (element);
- has_common_volume = snd_mixer_selem_has_common_volume (element);
-
- GST_LOG ("[%s] CAPTURE: has_capture_volume=%d, has_common_volume=%d, "
- "has_capture_switch=%d, has_common_switch=%d, play_track=%p", name,
- has_capture_volume, has_common_volume, has_capture_switch,
- has_common_switch, play_track);
-
- if (has_capture_volume && !(play_track && has_common_volume)) {
- cap_track = gst_alsa_mixer_track_new (element, samename, i,
- GST_MIXER_TRACK_INPUT, FALSE, NULL, play_track != NULL);
- } else if (has_capture_switch && !(play_track && has_common_switch)) {
- cap_track = gst_alsa_mixer_track_new (element, samename, i,
- GST_MIXER_TRACK_INPUT, TRUE, NULL, play_track != NULL);
- }
- }
-
-
- if (play_track && cap_track) {
- GST_ALSA_MIXER_TRACK (play_track)->shared_mute =
- GST_ALSA_MIXER_TRACK (cap_track);
- GST_ALSA_MIXER_TRACK (cap_track)->shared_mute =
- GST_ALSA_MIXER_TRACK (play_track);
- }
-
- if (play_track)
- mixer->tracklist = g_list_append (mixer->tracklist, play_track);
-
- if (cap_track)
- mixer->tracklist = g_list_append (mixer->tracklist, cap_track);
-
- element = snd_mixer_elem_next (element);
- }
-
- for (item = mixer->tracklist; item != NULL; item = item->next) {
- snd_mixer_elem_t *temp;
-
- if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
- temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
- else
- temp = GST_ALSA_MIXER_TRACK (item->data)->element;
-
- snd_mixer_elem_set_callback (temp, gst_alsa_mixer_elem_handle_callback);
- snd_mixer_elem_set_callback_private (temp, mixer);
- }
-
- g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-static void
-task_monitor_alsa (gpointer data)
-{
- struct pollfd *pfds;
- unsigned int nfds, rnfds;
- unsigned short revents;
- GstAlsaMixer *mixer = (GstAlsaMixer *) data;
-
- g_static_rec_mutex_lock (mixer->rec_mutex);
-
- nfds = snd_mixer_poll_descriptors_count (mixer->handle);
- if (nfds <= 0) {
- GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds);
- /* FIXME: sleep ? stop monitoring ? */
- return;
- }
-
- pfds = g_newa (struct pollfd, nfds + 1);
- rnfds = snd_mixer_poll_descriptors (mixer->handle, pfds, nfds);
- g_assert (rnfds <= nfds);
-
- pfds[rnfds].fd = mixer->pfd[0];
- pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
- pfds[rnfds].revents = 0;
-
- g_static_rec_mutex_unlock (mixer->rec_mutex);
-
- GST_LOG ("task loop");
- poll (pfds, rnfds + 1, -1);
-
- g_static_rec_mutex_lock (mixer->rec_mutex);
-
- snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents);
- if (revents & POLLIN || revents & POLLPRI) {
- GST_DEBUG ("Handling events");
- snd_mixer_handle_events (mixer->handle);
- }
-
- g_static_rec_mutex_unlock (mixer->rec_mutex);
-}
-
-/* API */
-
-GstAlsaMixer *
-gst_alsa_mixer_new (const char *device, GstAlsaMixerDirection dir)
-{
- GstAlsaMixer *ret = NULL;
-
- g_return_val_if_fail (device != NULL, NULL);
-
- ret = g_new0 (GstAlsaMixer, 1);
-
- if (pipe (ret->pfd) == -1)
- goto error;
-
- ret->rec_mutex = g_new (GStaticRecMutex, 1);
- g_static_rec_mutex_init (ret->rec_mutex);
-
- ret->task_mutex = g_new (GStaticRecMutex, 1);
- g_static_rec_mutex_init (ret->task_mutex);
-
- ret->task = gst_task_create (task_monitor_alsa, ret);
- gst_task_set_lock (ret->task, ret->task_mutex);
-
- ret->device = g_strdup (device);
- ret->dir = dir;
-
- if (!gst_alsa_mixer_open (ret))
- goto error;
-
- if (gst_task_start (ret->task) == FALSE) {
- GST_WARNING ("Could not start alsamixer task");
- }
-
- return ret;
-
- /* ERRORS */
-error:
- {
- gst_alsa_mixer_free (ret);
- return NULL;
- }
-}
-
-void
-gst_alsa_mixer_free (GstAlsaMixer * mixer)
-{
- g_return_if_fail (mixer != NULL);
-
- if (mixer->task) {
- if (write (mixer->pfd[1], "stop", 5) <= 0) {
- GST_ERROR ("Cannot send " "stop" " to alsamixer task");
- close (mixer->pfd[1]);
- mixer->pfd[1] = -1;
- }
-
- if (gst_task_join (mixer->task) == FALSE) {
- GST_ERROR ("Cannot join alsamixer task");
- }
-
- gst_object_unref (mixer->task);
- mixer->task = NULL;
- }
-
- g_static_rec_mutex_free (mixer->task_mutex);
- g_free (mixer->task_mutex);
- mixer->task_mutex = NULL;
-
- if (mixer->pfd[0] > 0) {
- close (mixer->pfd[0]);
- mixer->pfd[0] = -1;
- }
-
- if (mixer->pfd[1] > 0) {
- close (mixer->pfd[1]);
- mixer->pfd[1] = -1;
- }
-
- if (mixer->interface) {
- g_object_unref (G_OBJECT (mixer->interface));
- mixer->interface = NULL;
- }
-
- if (mixer->device) {
- g_free (mixer->device);
- mixer->device = NULL;
- }
-
- if (mixer->cardname) {
- g_free (mixer->cardname);
- mixer->cardname = NULL;
- }
-
- if (mixer->tracklist) {
- g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL);
- g_list_free (mixer->tracklist);
- mixer->tracklist = NULL;
- }
-
- if (mixer->handle) {
- snd_mixer_close (mixer->handle);
- mixer->handle = NULL;
- }
-
- g_static_rec_mutex_free (mixer->rec_mutex);
- g_free (mixer->rec_mutex);
- mixer->rec_mutex = NULL;
-
- g_free (mixer);
-}
-
-const GList *
-gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer)
-{
- g_return_val_if_fail (mixer->handle != NULL, NULL);
-
- gst_alsa_mixer_ensure_track_list (mixer);
-
- return (const GList *) mixer->tracklist;
-}
-
-void
-gst_alsa_mixer_get_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
- gint * volumes)
-{
- gint i;
- GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
- g_return_if_fail (mixer->handle != NULL);
-
- gst_alsa_mixer_track_update (alsa_track);
-
- if (track->flags & GST_MIXER_TRACK_OUTPUT) { /* return playback volume */
-
- /* Is emulated mute flag activated? */
- if (track->flags & GST_MIXER_TRACK_MUTE &&
- !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) {
- for (i = 0; i < track->num_channels; i++)
- volumes[i] = alsa_track->volumes[i];
- } else {
- for (i = 0; i < track->num_channels; i++) {
- long tmp = 0;
-
- snd_mixer_selem_get_playback_volume (alsa_track->element, i, &tmp);
- alsa_track->volumes[i] = volumes[i] = (gint) tmp;
- }
- }
-
- } else if (track->flags & GST_MIXER_TRACK_INPUT) { /* return capture volume */
-
- /* Is emulated record flag activated? */
- if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH ||
- track->flags & GST_MIXER_TRACK_RECORD) {
- for (i = 0; i < track->num_channels; i++) {
- long tmp = 0;
-
- snd_mixer_selem_get_capture_volume (alsa_track->element, i, &tmp);
- alsa_track->volumes[i] = volumes[i] = (gint) tmp;
- }
- } else {
- for (i = 0; i < track->num_channels; i++)
- volumes[i] = alsa_track->volumes[i];
- }
- }
-}
-
-static gboolean
-check_if_volumes_are_the_same (guint num_channels, gint * volumes)
-{
- guint i;
-
- if (num_channels <= 1)
- return TRUE;
-
- for (i = 1; i < num_channels; i++) {
- if (volumes[i] != volumes[0])
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
-gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
- gint * volumes)
-{
- GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
- gint i;
-
- g_return_if_fail (mixer->handle != NULL);
-
- gst_alsa_mixer_track_update (alsa_track);
-
- if (track->flags & GST_MIXER_TRACK_OUTPUT) {
-
- /* Is emulated mute flag activated? */
- if (track->flags & GST_MIXER_TRACK_MUTE &&
- !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) {
- for (i = 0; i < track->num_channels; i++)
- alsa_track->volumes[i] = volumes[i];
- } else {
- if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
- snd_mixer_selem_set_playback_volume_all (alsa_track->element,
- volumes[0]);
- for (i = 0; i < track->num_channels; i++)
- alsa_track->volumes[i] = volumes[0];
- } else {
- for (i = 0; i < track->num_channels; i++) {
- alsa_track->volumes[i] = volumes[i];
- snd_mixer_selem_set_playback_volume (alsa_track->element, i,
- volumes[i]);
- }
- }
- }
-
- } else if (track->flags & GST_MIXER_TRACK_INPUT) {
-
- /* Is emulated record flag activated? */
- if (track->flags & GST_MIXER_TRACK_RECORD ||
- alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) {
- if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
- snd_mixer_selem_set_capture_volume_all (alsa_track->element,
- volumes[0]);
- for (i = 0; i < track->num_channels; i++)
- alsa_track->volumes[i] = volumes[0];
- } else {
- for (i = 0; i < track->num_channels; i++) {
- alsa_track->volumes[i] = volumes[i];
- snd_mixer_selem_set_capture_volume (alsa_track->element, i,
- volumes[i]);
- }
- }
- } else {
- for (i = 0; i < track->num_channels; i++)
- alsa_track->volumes[i] = volumes[i];
- }
- }
-}
-
-void
-gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track,
- gboolean mute)
-{
- GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
- g_return_if_fail (mixer->handle != NULL);
-
- gst_alsa_mixer_track_update (alsa_track);
-
- if (!!(mute) == !!(track->flags & GST_MIXER_TRACK_MUTE))
- return;
-
- if (mute) {
- track->flags |= GST_MIXER_TRACK_MUTE;
-
- if (alsa_track->shared_mute)
- ((GstMixerTrack *) (alsa_track->shared_mute))->flags |=
- GST_MIXER_TRACK_MUTE;
- } else {
- track->flags &= ~GST_MIXER_TRACK_MUTE;
-
- if (alsa_track->shared_mute)
- ((GstMixerTrack *) (alsa_track->shared_mute))->flags &=
- ~GST_MIXER_TRACK_MUTE;
- }
-
- if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH) {
- snd_mixer_selem_set_playback_switch_all (alsa_track->element, mute ? 0 : 1);
- } else {
- gint i;
- GstAlsaMixerTrack *ctrl_track;
-
- if ((track->flags & GST_MIXER_TRACK_INPUT)
- && alsa_track->shared_mute != NULL)
- ctrl_track = alsa_track->shared_mute;
- else
- ctrl_track = alsa_track;
-
- for (i = 0; i < ((GstMixerTrack *) ctrl_track)->num_channels; i++) {
- long vol =
- mute ? ((GstMixerTrack *) ctrl_track)->min_volume : ctrl_track->
- volumes[i];
- snd_mixer_selem_set_playback_volume (ctrl_track->element, i, vol);
- }
- }
-}
-
-void
-gst_alsa_mixer_set_record (GstAlsaMixer * mixer,
- GstMixerTrack * track, gboolean record)
-{
- GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
-
- g_return_if_fail (mixer->handle != NULL);
-
- gst_alsa_mixer_track_update (alsa_track);
-
- if (!!(record) == !!(track->flags & GST_MIXER_TRACK_RECORD))
- return;
-
- if (record) {
- track->flags |= GST_MIXER_TRACK_RECORD;
- } else {
- track->flags &= ~GST_MIXER_TRACK_RECORD;
- }
-
- if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) {
- snd_mixer_selem_set_capture_switch_all (alsa_track->element,
- record ? 1 : 0);
-
- /* update all tracks in same exlusive cswitch group */
- if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL) {
- GList *item;
-
- for (item = mixer->tracklist; item != NULL; item = item->next) {
-
- if (GST_IS_ALSA_MIXER_TRACK (item->data)) {
- GstAlsaMixerTrack *item_alsa_track =
- GST_ALSA_MIXER_TRACK (item->data);
-
- if (item_alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL &&
- item_alsa_track->capture_group == alsa_track->capture_group) {
- gst_alsa_mixer_track_update (item_alsa_track);
- }
- }
- }
- }
- } else {
- gint i;
-
- for (i = 0; i < track->num_channels; i++) {
- long vol = record ? alsa_track->volumes[i] : track->min_volume;
-
- snd_mixer_selem_set_capture_volume (alsa_track->element, i, vol);
- }
- }
-}
-
-void
-gst_alsa_mixer_set_option (GstAlsaMixer * mixer,
- GstMixerOptions * opts, gchar * value)
-{
- gint idx = -1, n = 0;
- GList *item;
- GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
-
- g_return_if_fail (mixer->handle != NULL);
-
- for (item = opts->values; item != NULL; item = item->next, n++) {
- if (!strcmp (item->data, value)) {
- idx = n;
- break;
- }
- }
- if (idx == -1)
- return;
-
- snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx);
-}
-
-const gchar *
-gst_alsa_mixer_get_option (GstAlsaMixer * mixer, GstMixerOptions * opts)
-{
- gint ret;
- guint idx;
- GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts);
-
- g_return_val_if_fail (mixer->handle != NULL, NULL);
-
- ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
- if (ret == 0)
- return g_list_nth_data (opts->values, idx);
- else
- return snd_strerror (ret); /* feeble attempt at error handling */
-}
-
-GstMixerFlags
-gst_alsa_mixer_get_mixer_flags (GstAlsaMixer * mixer)
-{
- g_return_val_if_fail (mixer != NULL, GST_MIXER_FLAG_NONE);
-
- return GST_MIXER_FLAG_AUTO_NOTIFICATIONS;
-}
-
-static void
-gst_alsa_mixer_update_option (GstAlsaMixer * mixer,
- GstAlsaMixerOptions * alsa_opts)
-{
- gint ret;
- guint idx;
- /* const */ gchar *option;
-
- if (mixer->interface == NULL) {
- GST_WARNING ("Cannot send update notifications, no GstMixer * given");
- return;
- }
-
- ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx);
- if (ret == 0) {
- option = g_list_nth_data (GST_MIXER_OPTIONS (alsa_opts)->values, idx);
- gst_mixer_option_changed (mixer->interface, GST_MIXER_OPTIONS (alsa_opts),
- option);
- }
-}
-
-static void
-gst_alsa_mixer_update_track (GstAlsaMixer * mixer,
- GstAlsaMixerTrack * alsa_track)
-{
- GstMixerTrack *track = (GstMixerTrack *) alsa_track;
- gboolean old_mute;
- gboolean old_record;
- gint i, n_channels;
- gint *old_volumes;
-
- GST_DEBUG ("Updating track %" GST_PTR_FORMAT, alsa_track);
-
- if (mixer->interface == NULL) {
- GST_WARNING ("Cannot send update notifications, no GstMixer * given");
- return;
- }
-
- old_mute = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE));
- old_record = !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD));
- old_volumes = g_new (gint, track->num_channels);
- n_channels = track->num_channels;
- memcpy (old_volumes, alsa_track->volumes,
- sizeof (gint) * track->num_channels);
-
- gst_alsa_mixer_track_update (alsa_track);
-
- if (old_record !=
- !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) {
- gst_mixer_record_toggled (mixer->interface, track,
- !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD));
- }
- if (old_mute != !!(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))) {
- gst_mixer_mute_toggled (mixer->interface, track,
- !!GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE));
- }
-
- n_channels = MIN (n_channels, track->num_channels);
- for (i = 0; i < n_channels; i++) {
- if (old_volumes[i] != alsa_track->volumes[i]) {
- gst_mixer_volume_changed (mixer->interface, track, alsa_track->volumes);
- break;
- }
- }
- g_free (old_volumes);
-}
-
-/* utility function for gstalsamixerelement to set the interface */
-void
-_gst_alsa_mixer_set_interface (GstAlsaMixer * mixer, GstMixer * interface)
-{
- g_return_if_fail (mixer != NULL && mixer->interface == NULL);
- g_return_if_fail (interface != NULL);
-
- mixer->interface = g_object_ref (G_OBJECT (interface));
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixer.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/* ALSA mixer interface implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_H__
-#define __GST_ALSA_MIXER_H__
-
-
-#include "gstalsa.h"
-
-#include <gst/interfaces/mixer.h>
-#include "gstalsamixeroptions.h"
-#include "gstalsamixertrack.h"
-
-
-G_BEGIN_DECLS
-
-/* This does not get you what you think it does, use obj->mixer */
-/* #define GST_ALSA_MIXER(obj) ((GstAlsaMixer*)(obj)) */
-
-typedef struct _GstAlsaMixer GstAlsaMixer;
-
-typedef enum {
- GST_ALSA_MIXER_CAPTURE = 1<<0,
- GST_ALSA_MIXER_PLAYBACK = 1<<1,
- GST_ALSA_MIXER_ALL = GST_ALSA_MIXER_CAPTURE | GST_ALSA_MIXER_PLAYBACK
-} GstAlsaMixerDirection;
-
-/**
- * GstAlsaMixer:
- *
- * Opaque data structure
- */
-struct _GstAlsaMixer
-{
- GList * tracklist; /* list of available tracks */
-
- snd_mixer_t * handle;
-
- GstTask * task;
- GStaticRecMutex * task_mutex;
- GStaticRecMutex * rec_mutex;
-
- int pfd[2];
-
- GstMixer * interface;
- gchar * device;
- gchar * cardname;
-
- GstAlsaMixerDirection dir;
-};
-
-
-GstAlsaMixer* gst_alsa_mixer_new (const gchar *device,
- GstAlsaMixerDirection dir);
-void gst_alsa_mixer_free (GstAlsaMixer *mixer);
-
-const GList* gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer);
-void gst_alsa_mixer_set_volume (GstAlsaMixer * mixer,
- GstMixerTrack * track,
- gint * volumes);
-void gst_alsa_mixer_get_volume (GstAlsaMixer * mixer,
- GstMixerTrack * track,
- gint * volumes);
-void gst_alsa_mixer_set_record (GstAlsaMixer * mixer,
- GstMixerTrack * track,
- gboolean record);
-void gst_alsa_mixer_set_mute (GstAlsaMixer * mixer,
- GstMixerTrack * track,
- gboolean mute);
-void gst_alsa_mixer_set_option (GstAlsaMixer * mixer,
- GstMixerOptions * opts,
- gchar * value);
-const gchar* gst_alsa_mixer_get_option (GstAlsaMixer * mixer,
- GstMixerOptions * opts);
-void _gst_alsa_mixer_set_interface (GstAlsaMixer * mixer,
- GstMixer * interface);
-GstMixerFlags gst_alsa_mixer_get_mixer_flags (GstAlsaMixer *mixer);
-
-#define GST_IMPLEMENT_ALSA_MIXER_METHODS(Type, interface_as_function) \
-static gboolean \
-interface_as_function ## _supported (Type *this, GType iface_type) \
-{ \
- g_assert (iface_type == GST_TYPE_MIXER); \
- \
- return (this->mixer != NULL); \
-} \
- \
-static const GList* \
-interface_as_function ## _list_tracks (GstMixer * mixer) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_val_if_fail (this != NULL, NULL); \
- g_return_val_if_fail (this->mixer != NULL, NULL); \
- \
- return gst_alsa_mixer_list_tracks (this->mixer); \
-} \
- \
-static void \
-interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
- gint * volumes) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_if_fail (this != NULL); \
- g_return_if_fail (this->mixer != NULL); \
- \
- gst_alsa_mixer_set_volume (this->mixer, track, volumes); \
-} \
- \
-static void \
-interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
- gint * volumes) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_if_fail (this != NULL); \
- g_return_if_fail (this->mixer != NULL); \
- \
- gst_alsa_mixer_get_volume (this->mixer, track, volumes); \
-} \
- \
-static void \
-interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
- gboolean record) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_if_fail (this != NULL); \
- g_return_if_fail (this->mixer != NULL); \
- \
- gst_alsa_mixer_set_record (this->mixer, track, record); \
-} \
- \
-static void \
-interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
- gboolean mute) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_if_fail (this != NULL); \
- g_return_if_fail (this->mixer != NULL); \
- \
- gst_alsa_mixer_set_mute (this->mixer, track, mute); \
-} \
- \
-static void \
-interface_as_function ## _set_option (GstMixer * mixer, GstMixerOptions * opts, \
- gchar * value) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_if_fail (this != NULL); \
- g_return_if_fail (this->mixer != NULL); \
- \
- gst_alsa_mixer_set_option (this->mixer, opts, value); \
-} \
- \
-static const gchar* \
-interface_as_function ## _get_option (GstMixer * mixer, GstMixerOptions * opts) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_val_if_fail (this != NULL, NULL); \
- g_return_val_if_fail (this->mixer != NULL, NULL); \
- \
- return gst_alsa_mixer_get_option (this->mixer, opts); \
-} \
- \
-static GstMixerFlags \
-interface_as_function ## _get_mixer_flags (GstMixer * mixer) \
-{ \
- Type *this = (Type*) mixer; \
- \
- g_return_val_if_fail (this != NULL, GST_MIXER_FLAG_NONE); \
- g_return_val_if_fail (this->mixer != NULL, GST_MIXER_FLAG_NONE); \
- \
- return gst_alsa_mixer_get_mixer_flags (this->mixer); \
-} \
- \
-static void \
-interface_as_function ## _interface_init (GstMixerClass * klass) \
-{ \
- GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \
- \
- /* set up the interface hooks */ \
- klass->list_tracks = interface_as_function ## _list_tracks; \
- klass->set_volume = interface_as_function ## _set_volume; \
- klass->get_volume = interface_as_function ## _get_volume; \
- klass->set_mute = interface_as_function ## _set_mute; \
- klass->set_record = interface_as_function ## _set_record; \
- klass->set_option = interface_as_function ## _set_option; \
- klass->get_option = interface_as_function ## _get_option; \
- klass->get_mixer_flags = interface_as_function ## _get_mixer_flags; \
-}
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixerelement.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,248 +0,0 @@
-/* ALSA mixer implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixerelement.h"
-#include "gstalsadeviceprobe.h"
-
-#define DEFAULT_PROP_DEVICE "default"
-#define DEFAULT_PROP_DEVICE_NAME ""
-
-enum
-{
- PROP_0,
- PROP_DEVICE,
- PROP_DEVICE_NAME
-};
-
-static const GstElementDetails gst_alsa_mixer_element_details =
-GST_ELEMENT_DETAILS ("Alsa mixer",
- "Generic/Audio",
- "Control sound input and output levels with ALSA",
- "Leif Johnson <leif@ambient.2y.net>");
-
-static void gst_alsa_mixer_element_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaMixerElement, gst_alsa_mixer_element,
- GstElement, GST_TYPE_ELEMENT, gst_alsa_mixer_element_init_interfaces);
-
-/* massive macro that takes care of all the GstMixer stuff */
-GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaMixerElement, gst_alsa_mixer_element);
-
-static void gst_alsa_mixer_element_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static void gst_alsa_mixer_element_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsa_mixer_element_finalize (GObject * object);
-
-static GstStateChangeReturn gst_alsa_mixer_element_change_state (GstElement
- * element, GstStateChange transition);
-
-static gboolean
-gst_alsa_mixer_element_interface_supported (GstAlsaMixerElement * this,
- GType interface_type)
-{
- if (interface_type == GST_TYPE_MIXER) {
- return gst_alsa_mixer_element_supported (this, interface_type);
- }
-
- g_return_val_if_reached (FALSE);
-}
-
-static void
-gst_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
- klass->supported = (gpointer) gst_alsa_mixer_element_interface_supported;
-}
-
-static void
-gst_alsa_mixer_element_init_interfaces (GType type)
-{
- static const GInterfaceInfo implements_iface_info = {
- (GInterfaceInitFunc) gst_implements_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo mixer_iface_info = {
- (GInterfaceInitFunc) gst_alsa_mixer_element_interface_init,
- NULL,
- NULL,
- };
-
- g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
- &implements_iface_info);
- g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
-
- gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsa_mixer_element_base_init (gpointer klass)
-{
- gst_element_class_set_details (GST_ELEMENT_CLASS (klass),
- &gst_alsa_mixer_element_details);
-}
-
-static void
-gst_alsa_mixer_element_class_init (GstAlsaMixerElementClass * klass)
-{
- GstElementClass *element_class;
- GObjectClass *gobject_class;
-
- element_class = (GstElementClass *) klass;
- gobject_class = (GObjectClass *) klass;
-
- gobject_class->finalize = gst_alsa_mixer_element_finalize;
- gobject_class->get_property = gst_alsa_mixer_element_get_property;
- gobject_class->set_property = gst_alsa_mixer_element_set_property;
-
- g_object_class_install_property (gobject_class, PROP_DEVICE,
- g_param_spec_string ("device", "Device",
- "ALSA device, as defined in an asound configuration file",
- DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
- g_param_spec_string ("device-name", "Device name",
- "Human-readable name of the sound device",
- DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
-
- element_class->change_state =
- GST_DEBUG_FUNCPTR (gst_alsa_mixer_element_change_state);
-}
-
-static void
-gst_alsa_mixer_element_finalize (GObject * obj)
-{
- GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (obj);
-
- g_free (this->device);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_alsa_mixer_element_init (GstAlsaMixerElement * this,
- GstAlsaMixerElementClass * klass)
-{
- this->mixer = NULL;
- this->device = g_strdup (DEFAULT_PROP_DEVICE);
-}
-
-static void
-gst_alsa_mixer_element_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
-
- switch (prop_id) {
- case PROP_DEVICE:{
- GST_OBJECT_LOCK (this);
- g_free (this->device);
- this->device = g_value_dup_string (value);
- /* make sure we never set NULL, this is nice when we want to open the
- * device. */
- if (this->device == NULL)
- this->device = g_strdup (DEFAULT_PROP_DEVICE);
- GST_OBJECT_UNLOCK (this);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_alsa_mixer_element_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object);
-
- switch (prop_id) {
- case PROP_DEVICE:{
- GST_OBJECT_LOCK (this);
- g_value_set_string (value, this->device);
- GST_OBJECT_UNLOCK (this);
- break;
- }
- case PROP_DEVICE_NAME:{
- GST_OBJECT_LOCK (this);
- if (this->mixer) {
- g_value_set_string (value, this->mixer->cardname);
- } else {
- g_value_set_string (value, NULL);
- }
- GST_OBJECT_UNLOCK (this);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static GstStateChangeReturn
-gst_alsa_mixer_element_change_state (GstElement * element,
- GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!this->mixer) {
- this->mixer = gst_alsa_mixer_new (this->device, GST_ALSA_MIXER_ALL);
- if (!this->mixer)
- goto open_failed;
- _gst_alsa_mixer_set_interface (this->mixer, GST_MIXER (element));
- }
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
- if (ret == GST_STATE_CHANGE_FAILURE)
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_NULL:
- if (this->mixer) {
- gst_alsa_mixer_free (this->mixer);
- this->mixer = NULL;
- }
- break;
- default:
- break;
- }
-
- return ret;
-
- /* ERRORS */
-open_failed:
- {
- GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL),
- ("Failed to open alsa mixer device '%s'", this->device));
- return GST_STATE_CHANGE_FAILURE;
- }
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixerelement.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* ALSA mixer interface implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_ELEMENT_H__
-#define __GST_ALSA_MIXER_ELEMENT_H__
-
-
-#include "gstalsa.h"
-#include "gstalsamixer.h"
-
-G_BEGIN_DECLS
-
-#define GST_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElement))
-#define GST_ALSA_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElementClass))
-#define GST_IS_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_ELEMENT))
-#define GST_IS_ALSA_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_ELEMENT))
-#define GST_TYPE_ALSA_MIXER_ELEMENT (gst_alsa_mixer_element_get_type())
-
-typedef struct _GstAlsaMixerElement GstAlsaMixerElement;
-typedef struct _GstAlsaMixerElementClass GstAlsaMixerElementClass;
-
-/**
- * GstAlsaMixerElement
- *
- * Opaque datastructure.
- */
-struct _GstAlsaMixerElement {
- GstElement parent;
-
- GstAlsaMixer *mixer;
- gchar *device;
-};
-
-struct _GstAlsaMixerElementClass {
- GstElementClass parent;
-};
-
-
-GType gst_alsa_mixer_element_get_type (void);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_ELEMENT_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixeroptions.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* ALSA mixer object implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsamixeroptions.h"
-
-static void gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts);
-static void gst_alsa_mixer_options_class_init (gpointer g_class,
- gpointer class_data);
-
-static GstMixerOptionsClass *parent_class = NULL;
-
-GType
-gst_alsa_mixer_options_get_type (void)
-{
- static GType opts_type = 0;
-
- if (!opts_type) {
- static const GTypeInfo opts_info = {
- sizeof (GstAlsaMixerOptionsClass),
- NULL,
- NULL,
- gst_alsa_mixer_options_class_init,
- NULL,
- NULL,
- sizeof (GstAlsaMixerOptions),
- 0,
- (GInstanceInitFunc) gst_alsa_mixer_options_init,
- };
-
- opts_type =
- g_type_register_static (GST_TYPE_MIXER_OPTIONS, "GstAlsaMixerOptions",
- &opts_info, 0);
- }
-
- return opts_type;
-}
-
-static void
-gst_alsa_mixer_options_class_init (gpointer g_class, gpointer class_data)
-{
- parent_class = g_type_class_peek_parent (g_class);
-}
-
-static void
-gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts)
-{
-}
-
-GstMixerOptions *
-gst_alsa_mixer_options_new (snd_mixer_elem_t * element, gint track_num)
-{
- GstMixerOptions *opts;
- GstAlsaMixerOptions *alsa_opts;
- GstMixerTrack *track;
- const gchar *label;
- gint num, i;
- gchar str[256];
-
- label = snd_mixer_selem_get_name (element);
-
- opts = g_object_new (GST_ALSA_MIXER_OPTIONS_TYPE,
- "untranslated-label", label, NULL);
- alsa_opts = (GstAlsaMixerOptions *) opts;
- track = (GstMixerTrack *) opts;
-
- /* set basic information */
- track->label = g_strdup (label); /* FIXME: translate this? */
- track->num_channels = 0;
- track->flags = 0;
- alsa_opts->element = element;
- alsa_opts->track_num = track_num;
-
- /* get enumerations for switch/options object */
- num = snd_mixer_selem_get_enum_items (element);
- for (i = 0; i < num; i++) {
- if (snd_mixer_selem_get_enum_item_name (element, i, 255, str) < 0) {
- g_object_unref (G_OBJECT (alsa_opts));
- return NULL;
- }
-
- opts->values = g_list_append (opts->values, g_strdup (str));
- }
-
- return opts;
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixeroptions.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* ALSA mixer options object.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_OPTIONS_H__
-#define __GST_ALSA_MIXER_OPTIONS_H__
-
-
-#include "gstalsa.h"
-#include <gst/interfaces/mixeroptions.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_ALSA_MIXER_OPTIONS_TYPE (gst_alsa_mixer_options_get_type ())
-#define GST_ALSA_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptions))
-#define GST_ALSA_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptionsClass))
-#define GST_IS_ALSA_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_OPTIONS))
-#define GST_IS_ALSA_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_OPTIONS))
-#define GST_TYPE_ALSA_MIXER_OPTIONS (gst_alsa_mixer_options_get_type())
-
-
-typedef struct _GstAlsaMixerOptions GstAlsaMixerOptions;
-typedef struct _GstAlsaMixerOptionsClass GstAlsaMixerOptionsClass;
-
-
-struct _GstAlsaMixerOptions {
- GstMixerOptions parent;
- snd_mixer_elem_t *element; /* the ALSA mixer element for this track */
- gint track_num;
-};
-
-struct _GstAlsaMixerOptionsClass {
- GstMixerOptionsClass parent;
-};
-
-
-GType gst_alsa_mixer_options_get_type (void);
-GstMixerOptions *gst_alsa_mixer_options_new (snd_mixer_elem_t * element,
- gint track_num);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_OPTIONS_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsamixertrack.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/* ALSA mixer track implementation.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst-i18n-plugin.h>
-
-#include "gstalsamixertrack.h"
-
-static void gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track);
-static void gst_alsa_mixer_track_class_init (gpointer g_class,
- gpointer class_data);
-
-static GstMixerTrackClass *parent_class = NULL;
-
-GType
-gst_alsa_mixer_track_get_type (void)
-{
- static GType track_type = 0;
-
- if (!track_type) {
- static const GTypeInfo track_info = {
- sizeof (GstAlsaMixerTrackClass),
- NULL,
- NULL,
- gst_alsa_mixer_track_class_init,
- NULL,
- NULL,
- sizeof (GstAlsaMixerTrack),
- 0,
- (GInstanceInitFunc) gst_alsa_mixer_track_init,
- NULL
- };
-
- track_type =
- g_type_register_static (GST_TYPE_MIXER_TRACK, "GstAlsaMixerTrack",
- &track_info, 0);
- }
-
- return track_type;
-}
-
-static void
-gst_alsa_mixer_track_class_init (gpointer g_class, gpointer class_data)
-{
- parent_class = g_type_class_peek_parent (g_class);
-}
-
-static void
-gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track)
-{
-}
-
-static void
-gst_alsa_mixer_track_update_alsa_capabilities (GstAlsaMixerTrack * alsa_track)
-{
- alsa_track->alsa_flags = 0;
- alsa_track->capture_group = -1;
-
- if (snd_mixer_selem_has_common_volume (alsa_track->element))
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_VOLUME;
-
- if (snd_mixer_selem_has_playback_volume (alsa_track->element))
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PVOLUME;
-
- if (snd_mixer_selem_has_capture_volume (alsa_track->element))
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CVOLUME;
-
- if (snd_mixer_selem_has_common_switch (alsa_track->element))
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_SWITCH;
-
- if (snd_mixer_selem_has_playback_switch (alsa_track->element))
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PSWITCH;
-
- if (snd_mixer_selem_has_capture_switch (alsa_track->element)) {
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH;
-
- if (snd_mixer_selem_has_capture_switch_exclusive (alsa_track->element)) {
- alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH_EXCL;
- alsa_track->capture_group =
- snd_mixer_selem_get_capture_group (alsa_track->element);
- }
- }
-
- GST_LOG ("[%s] alsa_flags=0x%08x, capture_group=%d",
- snd_mixer_selem_get_name (alsa_track->element),
- alsa_track->alsa_flags, alsa_track->capture_group);
-}
-
-inline static gboolean
-alsa_track_has_cap (GstAlsaMixerTrack * alsa_track, guint32 flag)
-{
- return ((alsa_track->alsa_flags & flag) != 0);
-}
-
-GstMixerTrack *
-gst_alsa_mixer_track_new (snd_mixer_elem_t * element,
- gint num, gint track_num, gint flags, gboolean sw,
- GstAlsaMixerTrack * shared_mute_track, gboolean append_capture)
-{
- GstAlsaMixerTrack *alsa_track;
- GstMixerTrack *track;
- const gchar *name;
- const gchar *label;
- gint i;
- long min = 0, max = 0;
- const struct
- {
- const gchar orig[12];
- const gchar trans[12];
- } alsa_track_labels[] = {
- {
- "Master", N_("Master")}, {
- "Bass", N_("Bass")}, {
- "Treble", N_("Treble")}, {
- "PCM", N_("PCM")}, {
- "Synth", N_("Synth")}, {
- "Line", N_("Line-in")}, {
- "CD", N_("CD")}, {
- "Mic", N_("Microphone")}, {
- "PC Speaker", N_("PC Speaker")}, {
- "Playback", N_("Playback")}, {
- "Capture", N_("Capture")}
- };
-
- name = snd_mixer_selem_get_name (element);
-
- GST_LOG ("[%s] num=%d,track_num=%d,flags=0x%08x,sw=%s,shared_mute_track=%p",
- name, num, track_num, flags, (sw) ? "true" : "false", shared_mute_track);
-
- track = (GstMixerTrack *) g_object_new (GST_ALSA_MIXER_TRACK_TYPE,
- "untranslated-label", name, NULL);
-
- alsa_track = (GstAlsaMixerTrack *) track;
-
- GST_LOG ("[%s] created new mixer track %p", name, track);
-
- /* This reflects the assumptions used for GstAlsaMixerTrack */
- if (!(!!(flags & GST_MIXER_TRACK_OUTPUT) ^ !!(flags & GST_MIXER_TRACK_INPUT))) {
- GST_ERROR ("Mixer track must be either output or input!");
- g_return_val_if_reached (NULL);
- }
-
- track->flags = flags;
- alsa_track->element = element;
- alsa_track->shared_mute = shared_mute_track;
- alsa_track->track_num = track_num;
- alsa_track->alsa_channels = 0;
-
- gst_alsa_mixer_track_update_alsa_capabilities (alsa_track);
-
- if (flags & GST_MIXER_TRACK_OUTPUT) {
- while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS &&
- snd_mixer_selem_has_playback_channel (element,
- alsa_track->alsa_channels)) {
- alsa_track->alsa_channels++;
- }
- GST_LOG ("[%s] %d output channels", name, alsa_track->alsa_channels);
- } else if (flags & GST_MIXER_TRACK_INPUT) {
- while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS &&
- snd_mixer_selem_has_capture_channel (element,
- alsa_track->alsa_channels)) {
- alsa_track->alsa_channels++;
- }
- GST_LOG ("[%s] %d input channels", name, alsa_track->alsa_channels);
- } else {
- g_assert_not_reached ();
- }
-
- if (sw)
- track->num_channels = 0;
- else
- track->num_channels = alsa_track->alsa_channels;
-
- /* translate the name if we can */
- label = name;
- for (i = 0; i < G_N_ELEMENTS (alsa_track_labels); ++i) {
- if (g_utf8_collate (label, alsa_track_labels[i].orig) == 0) {
- label = _(alsa_track_labels[i].trans);
- break;
- }
- }
-
- if (num == 0) {
- track->label = g_strdup_printf ("%s%s%s", label,
- append_capture ? " " : "", append_capture ? _("Capture") : "");
- } else {
- track->label = g_strdup_printf ("%s%s%s %d", label,
- append_capture ? " " : "", append_capture ? _("Capture") : "", num);
- }
-
- /* set volume information */
- if (track->num_channels > 0) {
- if ((flags & GST_MIXER_TRACK_OUTPUT))
- snd_mixer_selem_get_playback_volume_range (element, &min, &max);
- else
- snd_mixer_selem_get_capture_volume_range (element, &min, &max);
- }
- track->min_volume = (gint) min;
- track->max_volume = (gint) max;
-
- for (i = 0; i < track->num_channels; i++) {
- long tmp = 0;
-
- if (flags & GST_MIXER_TRACK_OUTPUT)
- snd_mixer_selem_get_playback_volume (element, i, &tmp);
- else
- snd_mixer_selem_get_capture_volume (element, i, &tmp);
-
- alsa_track->volumes[i] = (gint) tmp;
- }
-
- gst_alsa_mixer_track_update (alsa_track);
-
- return track;
-}
-
-void
-gst_alsa_mixer_track_update (GstAlsaMixerTrack * alsa_track)
-{
- GstMixerTrack *track = (GstMixerTrack *) alsa_track;
- gint i;
- gint audible = !(track->flags & GST_MIXER_TRACK_MUTE);
-
- if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME)) {
- /* update playback volume */
- for (i = 0; i < track->num_channels; i++) {
- long vol = 0;
-
- snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol);
- alsa_track->volumes[i] = (gint) vol;
- }
- }
-
- if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME)) {
- /* update capture volume */
- for (i = 0; i < track->num_channels; i++) {
- long vol = 0;
-
- snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol);
- alsa_track->volumes[i] = (gint) vol;
- }
- }
-
- /* Any updates in flags? */
- if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PSWITCH)) {
- int v = 0;
-
- audible = 0;
- for (i = 0; i < alsa_track->alsa_channels; ++i) {
- snd_mixer_selem_get_playback_switch (alsa_track->element, i, &v);
- audible += v;
- }
-
- } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME) &&
- track->flags & GST_MIXER_TRACK_MUTE) {
- /* check if user has raised volume with a parallel running application */
-
- for (i = 0; i < track->num_channels; i++) {
- long vol = 0;
-
- snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol);
-
- if (vol > track->min_volume) {
- audible = 1;
- break;
- }
- }
- }
-
- if (!!(audible) != !(track->flags & GST_MIXER_TRACK_MUTE)) {
- if (audible) {
- track->flags &= ~GST_MIXER_TRACK_MUTE;
-
- if (alsa_track->shared_mute)
- ((GstMixerTrack *) (alsa_track->shared_mute))->flags &=
- ~GST_MIXER_TRACK_MUTE;
- } else {
- track->flags |= GST_MIXER_TRACK_MUTE;
-
- if (alsa_track->shared_mute)
- ((GstMixerTrack *) (alsa_track->shared_mute))->flags |=
- GST_MIXER_TRACK_MUTE;
- }
- }
-
- if (track->flags & GST_MIXER_TRACK_INPUT) {
- gint recording = track->flags & GST_MIXER_TRACK_RECORD;
-
- if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CSWITCH)) {
- int v = 0;
-
- recording = 0;
- for (i = 0; i < alsa_track->alsa_channels; ++i) {
- snd_mixer_selem_get_capture_switch (alsa_track->element, i, &v);
- recording += v;
- }
-
- } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME) &&
- !(track->flags & GST_MIXER_TRACK_RECORD)) {
- /* check if user has raised volume with a parallel running application */
-
- for (i = 0; i < track->num_channels; i++) {
- long vol = 0;
-
- snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol);
-
- if (vol > track->min_volume) {
- recording = 1;
- break;
- }
- }
- }
-
- if (recording)
- track->flags |= GST_MIXER_TRACK_RECORD;
- else
- track->flags &= ~GST_MIXER_TRACK_RECORD;
- }
-
-}
--- a/gst_plugins_base/ext/alsa/gstalsamixertrack.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/* ALSA mixer track object.
- * Copyright (C) 2003 Leif Johnson <leif@ambient.2y.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef __GST_ALSA_MIXER_TRACK_H__
-#define __GST_ALSA_MIXER_TRACK_H__
-
-
-#include "gstalsa.h"
-#include <gst/interfaces/mixertrack.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_ALSA_MIXER_TRACK_TYPE (gst_alsa_mixer_track_get_type ())
-#define GST_ALSA_MIXER_TRACK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrack))
-#define GST_ALSA_MIXER_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrackClass))
-#define GST_IS_ALSA_MIXER_TRACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_TRACK))
-#define GST_IS_ALSA_MIXER_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_TRACK))
-#define GST_TYPE_ALSA_MIXER_TRACK (gst_alsa_mixer_track_get_type())
-
-typedef struct _GstAlsaMixerTrack GstAlsaMixerTrack;
-typedef struct _GstAlsaMixerTrackClass GstAlsaMixerTrackClass;
-
-#define GST_ALSA_MIXER_TRACK_VOLUME (1<<0) /* common volume */
-#define GST_ALSA_MIXER_TRACK_PVOLUME (1<<1)
-#define GST_ALSA_MIXER_TRACK_CVOLUME (1<<2)
-#define GST_ALSA_MIXER_TRACK_SWITCH (1<<3) /* common switch */
-#define GST_ALSA_MIXER_TRACK_PSWITCH (1<<4)
-#define GST_ALSA_MIXER_TRACK_CSWITCH (1<<5)
-#define GST_ALSA_MIXER_TRACK_CSWITCH_EXCL (1<<6)
-
-#define GST_ALSA_MAX_CHANNELS (SND_MIXER_SCHN_LAST+1)
-
-struct _GstAlsaMixerTrack {
- GstMixerTrack parent;
- snd_mixer_elem_t *element; /* the ALSA mixer element for this track */
- GstAlsaMixerTrack *shared_mute;
- gint track_num;
- guint32 alsa_flags; /* alsa track capabilities */
- gint alsa_channels;
- gint capture_group;
- gint volumes[GST_ALSA_MAX_CHANNELS];
-};
-
-struct _GstAlsaMixerTrackClass {
- GstMixerTrackClass parent;
-};
-
-GType gst_alsa_mixer_track_get_type (void);
-GstMixerTrack * gst_alsa_mixer_track_new (snd_mixer_elem_t * element,
- gint num,
- gint track_num,
- gint flags,
- gboolean sw, /* is simple switch? */
- GstAlsaMixerTrack * shared_mute_track,
- gboolean label_append_capture);
-void gst_alsa_mixer_track_update (GstAlsaMixerTrack * alsa_track);
-
-G_END_DECLS
-
-
-#endif /* __GST_ALSA_MIXER_TRACK_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsaplugin.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2001 CodeFactory AB
- * Copyright (C) 2001 Thomas Nyberg <thomas@codefactory.se>
- * Copyright (C) 2001-2002 Andy Wingo <apwingo@eos.ncsu.edu>
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstalsasink.h"
-#include "gstalsasrc.h"
-#include "gstalsamixerelement.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-GST_DEBUG_CATEGORY (alsa_debug);
-
-/* ALSA debugging wrapper */
-static void
-gst_alsa_error_wrapper (const char *file, int line, const char *function,
- int err, const char *fmt, ...)
-{
-#ifndef GST_DISABLE_GST_DEBUG
- va_list args;
- gchar *str;
-
- va_start (args, fmt);
- str = g_strdup_vprintf (fmt, args);
- va_end (args);
- /* FIXME: use GST_LEVEL_ERROR here? Currently warning is used because we're
- * able to catch enough of the errors that would be printed otherwise
- */
- gst_debug_log (alsa_debug, GST_LEVEL_WARNING, file, function, line, NULL,
- "alsalib error: %s%s%s", str, err ? ": " : "",
- err ? snd_strerror (err) : "");
- g_free (str);
-#endif
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- int err;
-
- if (!gst_element_register (plugin, "alsamixer", GST_RANK_NONE,
- GST_TYPE_ALSA_MIXER_ELEMENT))
- return FALSE;
- if (!gst_element_register (plugin, "alsasrc", GST_RANK_PRIMARY,
- GST_TYPE_ALSA_SRC))
- return FALSE;
- if (!gst_element_register (plugin, "alsasink", GST_RANK_PRIMARY,
- GST_TYPE_ALSA_SINK))
- return FALSE;
-
- GST_DEBUG_CATEGORY_INIT (alsa_debug, "alsa", 0, "alsa plugins");
-
-#if ENABLE_NLS
- GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
- LOCALEDIR);
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
- err = snd_lib_error_set_handler (gst_alsa_error_wrapper);
- if (err != 0)
- GST_WARNING ("failed to set alsa error handler");
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "alsa",
- "ALSA plugin library",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/alsa/gstalsasink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,983 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
- *
- * gstalsasink.c:
- *
- * 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.
- */
-
-/**
- * SECTION:element-alsasink
- * @short_description: play audio to an ALSA device
- * @see_also: alsasrc, alsamixer
- *
- * <refsect2>
- * <para>
- * This element renders raw audio samples using the ALSA api.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Play an Ogg/Vorbis file.
- * </para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <alsa/asoundlib.h>
-
-#include "gstalsa.h"
-#include "gstalsasink.h"
-#include "gstalsadeviceprobe.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-/* elementfactory information */
-static const GstElementDetails gst_alsasink_details =
-GST_ELEMENT_DETAILS ("Audio sink (ALSA)",
- "Sink/Audio",
- "Output to a sound card via ALSA",
- "Wim Taymans <wim@fluendo.com>");
-
-#define DEFAULT_DEVICE "default"
-#define DEFAULT_DEVICE_NAME ""
-#define SPDIF_PERIOD_SIZE 1536
-#define SPDIF_BUFFER_SIZE 15360
-
-enum
-{
- PROP_0,
- PROP_DEVICE,
- PROP_DEVICE_NAME
-};
-
-static void gst_alsasink_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink,
- GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces);
-
-static void gst_alsasink_finalise (GObject * object);
-static void gst_alsasink_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsasink_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink);
-
-static gboolean gst_alsasink_open (GstAudioSink * asink);
-static gboolean gst_alsasink_prepare (GstAudioSink * asink,
- GstRingBufferSpec * spec);
-static gboolean gst_alsasink_unprepare (GstAudioSink * asink);
-static gboolean gst_alsasink_close (GstAudioSink * asink);
-static guint gst_alsasink_write (GstAudioSink * asink, gpointer data,
- guint length);
-static guint gst_alsasink_delay (GstAudioSink * asink);
-static void gst_alsasink_reset (GstAudioSink * asink);
-
-static gint output_ref; /* 0 */
-static snd_output_t *output; /* NULL */
-static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT;
-
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ALSA_SINK_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
-#else
-# define ALSA_SINK_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
-#endif
-
-static GstStaticPadTemplate alsasink_sink_factory =
- GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 32, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 24, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 8, "
- "depth = (int) 8, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];"
- "audio/x-iec958")
- );
-
-static void
-gst_alsasink_finalise (GObject * object)
-{
- GstAlsaSink *sink = GST_ALSA_SINK (object);
-
- g_free (sink->device);
- g_mutex_free (sink->alsa_lock);
-
- g_static_mutex_lock (&output_mutex);
- --output_ref;
- if (output_ref == 0) {
- snd_output_close (output);
- output = NULL;
- }
- g_static_mutex_unlock (&output_mutex);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_alsasink_init_interfaces (GType type)
-{
- gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsasink_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_alsasink_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&alsasink_sink_factory));
-}
-static void
-gst_alsasink_class_init (GstAlsaSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
- GstBaseAudioSinkClass *gstbaseaudiosink_class;
- GstAudioSinkClass *gstaudiosink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
- gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass;
- gstaudiosink_class = (GstAudioSinkClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasink_finalise);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasink_get_property);
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasink_set_property);
-
- gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps);
-
- gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open);
- gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare);
- gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare);
- gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close);
- gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write);
- gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay);
- gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset);
-
- g_object_class_install_property (gobject_class, PROP_DEVICE,
- g_param_spec_string ("device", "Device",
- "ALSA device, as defined in an asound configuration file",
- DEFAULT_DEVICE, G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
- g_param_spec_string ("device-name", "Device name",
- "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
- G_PARAM_READABLE));
-}
-
-static void
-gst_alsasink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAlsaSink *sink;
-
- sink = GST_ALSA_SINK (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- g_free (sink->device);
- sink->device = g_value_dup_string (value);
- /* setting NULL restores the default device */
- if (sink->device == NULL) {
- sink->device = g_strdup (DEFAULT_DEVICE);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_alsasink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAlsaSink *sink;
-
- sink = GST_ALSA_SINK (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- g_value_set_string (value, sink->device);
- break;
- case PROP_DEVICE_NAME:
- g_value_take_string (value,
- gst_alsa_find_device_name (GST_OBJECT_CAST (sink),
- sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class)
-{
- GST_DEBUG_OBJECT (alsasink, "initializing alsasink");
-
- alsasink->device = g_strdup (DEFAULT_DEVICE);
- alsasink->handle = NULL;
- alsasink->cached_caps = NULL;
- alsasink->alsa_lock = g_mutex_new ();
-
- g_static_mutex_lock (&output_mutex);
- if (output_ref == 0) {
- snd_output_stdio_attach (&output, stdout, 0);
- ++output_ref;
- }
- g_static_mutex_unlock (&output_mutex);
-}
-
-#define CHECK(call, error) \
-G_STMT_START { \
-if ((err = call) < 0) \
- goto error; \
-} G_STMT_END;
-
-static GstCaps *
-gst_alsasink_getcaps (GstBaseSink * bsink)
-{
- GstElementClass *element_class;
- GstPadTemplate *pad_template;
- GstAlsaSink *sink = GST_ALSA_SINK (bsink);
- GstCaps *caps;
-
- if (sink->handle == NULL) {
- GST_DEBUG_OBJECT (sink, "device not open, using template caps");
- return NULL; /* base class will get template caps for us */
- }
-
- if (sink->cached_caps) {
- GST_LOG_OBJECT (sink, "Returning cached caps");
- return gst_caps_ref (sink->cached_caps);
- }
-
- element_class = GST_ELEMENT_GET_CLASS (sink);
- pad_template = gst_element_class_get_pad_template (element_class, "sink");
- g_return_val_if_fail (pad_template != NULL, NULL);
-
- caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle,
- gst_pad_template_get_caps (pad_template));
-
- if (caps) {
- sink->cached_caps = gst_caps_ref (caps);
- }
-
- GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
-
- return caps;
-}
-
-static int
-set_hwparams (GstAlsaSink * alsa)
-{
- guint rrate;
- gint err, dir;
- snd_pcm_hw_params_t *params;
- guint period_time, buffer_time;
-
- snd_pcm_hw_params_malloc (¶ms);
-
- GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) "
- "SPDIF (%d)", alsa->channels, alsa->rate,
- snd_pcm_format_name (alsa->format), alsa->iec958);
-
- /* start with requested values, if we cannot configure alsa for those values,
- * we set these values to -1, which will leave the default alsa values */
- buffer_time = alsa->buffer_time;
- period_time = alsa->period_time;
-
-retry:
- /* choose all parameters */
- CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
- /* set the interleaved read/write format */
- CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
- wrong_access);
- /* set the sample format */
- if (alsa->iec958) {
- /* Try to use big endian first else fallback to le and swap bytes */
- if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) {
- alsa->format = SND_PCM_FORMAT_S16_LE;
- alsa->need_swap = TRUE;
- GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping");
- } else {
- alsa->need_swap = FALSE;
- }
- }
- CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
- no_sample_format);
- /* set the count of channels */
- CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
- no_channels);
- /* set the stream rate */
- rrate = alsa->rate;
- CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
- no_rate);
- if (rrate != alsa->rate)
- goto rate_match;
-
- /* get and dump some limits */
- {
- guint min, max;
-
- snd_pcm_hw_params_get_buffer_time_min (params, &min, &dir);
- snd_pcm_hw_params_get_buffer_time_max (params, &max, &dir);
-
- GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u",
- alsa->buffer_time, min, max);
-
- snd_pcm_hw_params_get_period_time_min (params, &min, &dir);
- snd_pcm_hw_params_get_period_time_max (params, &max, &dir);
-
- GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u",
- alsa->period_time, min, max);
-
- snd_pcm_hw_params_get_periods_min (params, &min, &dir);
- snd_pcm_hw_params_get_periods_max (params, &max, &dir);
-
- GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max);
- }
-
- /* now try to configure the buffer time and period time, if one
- * of those fail, we fall back to the defaults and emit a warning. */
- if (buffer_time != -1 && !alsa->iec958) {
- /* set the buffer time */
- if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
- &buffer_time, &dir)) < 0) {
- GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set buffer time %i for playback: %s",
- buffer_time, snd_strerror (err)));
- /* disable buffer_time the next round */
- buffer_time = -1;
- goto retry;
- }
- GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time);
- }
- if (period_time != -1 && !alsa->iec958) {
- /* set the period time */
- if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
- &period_time, &dir)) < 0) {
- GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set period time %i for playback: %s",
- period_time, snd_strerror (err)));
- /* disable period_time the next round */
- period_time = -1;
- goto retry;
- }
- GST_DEBUG_OBJECT (alsa, "period time %u", period_time);
- }
-
- /* Set buffer size and period size manually for SPDIF */
- if (G_UNLIKELY (alsa->iec958)) {
- snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE;
- snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE;
-
- CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params,
- &buffer_size), buffer_size);
- CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params,
- &period_size, NULL), period_size);
- }
-
- /* write the parameters to device */
- CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
-
- /* now get the configured values */
- CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
- buffer_size);
- CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
- period_size);
-
- GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size,
- alsa->period_size);
-
- snd_pcm_hw_params_free (params);
- return 0;
-
- /* ERRORS */
-no_config:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Broken configuration for playback: no configurations available: %s",
- snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-wrong_access:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Access type not available for playback: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_sample_format:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Sample format not available for playback: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_channels:
- {
- gchar *msg = NULL;
-
- if ((alsa->channels) == 1)
- msg = g_strdup (_("Could not open device for playback in mono mode."));
- if ((alsa->channels) == 2)
- msg = g_strdup (_("Could not open device for playback in stereo mode."));
- if ((alsa->channels) > 2)
- msg =
- g_strdup_printf (_
- ("Could not open device for playback in %d-channel mode."),
- alsa->channels);
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
- g_free (msg);
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_rate:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Rate %iHz not available for playback: %s",
- alsa->rate, snd_strerror (err)));
- return err;
- }
-rate_match:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
- snd_pcm_hw_params_free (params);
- return -EINVAL;
- }
-buffer_size:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to get buffer size for playback: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-period_size:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to get period size for playback: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-set_hw_params:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set hw params for playback: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-}
-
-static int
-set_swparams (GstAlsaSink * alsa)
-{
- int err;
- snd_pcm_sw_params_t *params;
-
- snd_pcm_sw_params_malloc (¶ms);
-
- /* get the current swparams */
- CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
- /* start the transfer when the buffer is almost full: */
- /* (buffer_size / avail_min) * avail_min */
- CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
- (alsa->buffer_size / alsa->period_size) * alsa->period_size),
- start_threshold);
-
- /* allow the transfer when at least period_size samples can be processed */
- CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
- alsa->period_size), set_avail);
-
-#if GST_CHECK_ALSA_VERSION(1,0,16)
- /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
-#else
- /* align all transfers to 1 sample */
- CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
-#endif
-
- /* write the parameters to the playback device */
- CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
-
- snd_pcm_sw_params_free (params);
- return 0;
-
- /* ERRORS */
-no_config:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to determine current swparams for playback: %s",
- snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-start_threshold:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set start threshold mode for playback: %s",
- snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-set_avail:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set avail min for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-#if !GST_CHECK_ALSA_VERSION(1,0,16)
-set_align:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set transfer align for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-#endif
-set_sw_params:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set sw params for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-}
-
-static gboolean
-alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec)
-{
- /* Initialize our boolean */
- alsa->iec958 = FALSE;
-
- switch (spec->type) {
- case GST_BUFTYPE_LINEAR:
- GST_DEBUG_OBJECT (alsa,
- "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth,
- spec->width, spec->sign, spec->bigend);
-
- alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
- spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
- break;
- case GST_BUFTYPE_FLOAT:
- switch (spec->format) {
- case GST_FLOAT32_LE:
- alsa->format = SND_PCM_FORMAT_FLOAT_LE;
- break;
- case GST_FLOAT32_BE:
- alsa->format = SND_PCM_FORMAT_FLOAT_BE;
- break;
- case GST_FLOAT64_LE:
- alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
- break;
- case GST_FLOAT64_BE:
- alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
- break;
- default:
- goto error;
- }
- break;
- case GST_BUFTYPE_A_LAW:
- alsa->format = SND_PCM_FORMAT_A_LAW;
- break;
- case GST_BUFTYPE_MU_LAW:
- alsa->format = SND_PCM_FORMAT_MU_LAW;
- break;
- case GST_BUFTYPE_IEC958:
- alsa->format = SND_PCM_FORMAT_S16_BE;
- alsa->iec958 = TRUE;
- break;
- default:
- goto error;
-
- }
- alsa->rate = spec->rate;
- alsa->channels = spec->channels;
- alsa->buffer_time = spec->buffer_time;
- alsa->period_time = spec->latency_time;
- alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
-
- return TRUE;
-
- /* ERRORS */
-error:
- {
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasink_open (GstAudioSink * asink)
-{
- GstAlsaSink *alsa;
- gint err;
-
- alsa = GST_ALSA_SINK (asink);
-
- CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK,
- SND_PCM_NONBLOCK), open_error);
- GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device);
-
- return TRUE;
-
- /* ERRORS */
-open_error:
- {
- if (err == -EBUSY) {
- GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
- (_("Could not open audio device for playback. "
- "Device is being used by another application.")),
- ("Device '%s' is busy", alsa->device));
- } else {
- GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE,
- (_("Could not open audio device for playback.")),
- ("Playback open error on device '%s': %s", alsa->device,
- snd_strerror (err)));
- }
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec)
-{
- GstAlsaSink *alsa;
- gint err;
-
- alsa = GST_ALSA_SINK (asink);
-
- if (spec->format == GST_IEC958) {
- snd_pcm_close (alsa->handle);
- alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa));
- if (G_UNLIKELY (!alsa->handle)) {
- goto no_iec958;
- }
- }
-
- if (!alsasink_parse_spec (alsa, spec))
- goto spec_parse;
-
- CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
-
- CHECK (set_hwparams (alsa), hw_params_failed);
- CHECK (set_swparams (alsa), sw_params_failed);
-
- alsa->bytes_per_sample = spec->bytes_per_sample;
- spec->segsize = alsa->period_size * spec->bytes_per_sample;
- spec->segtotal = alsa->buffer_size / alsa->period_size;
-
- {
- snd_output_t *out_buf = NULL;
- char *msg = NULL;
-
- snd_output_buffer_open (&out_buf);
- snd_pcm_dump_hw_setup (alsa->handle, out_buf);
- snd_output_buffer_string (out_buf, &msg);
- GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg);
- snd_output_close (out_buf);
- snd_output_buffer_open (&out_buf);
- snd_pcm_dump_sw_setup (alsa->handle, out_buf);
- snd_output_buffer_string (out_buf, &msg);
- GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg);
- snd_output_close (out_buf);
- }
-
- return TRUE;
-
- /* ERRORS */
-no_iec958:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL),
- ("Could not open IEC958 (SPDIF) device for playback"));
- return FALSE;
- }
-spec_parse:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Error parsing spec"));
- return FALSE;
- }
-non_block:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not set device to blocking: %s", snd_strerror (err)));
- return FALSE;
- }
-hw_params_failed:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Setting of hwparams failed: %s", snd_strerror (err)));
- return FALSE;
- }
-sw_params_failed:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Setting of swparams failed: %s", snd_strerror (err)));
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasink_unprepare (GstAudioSink * asink)
-{
- GstAlsaSink *alsa;
- gint err;
-
- alsa = GST_ALSA_SINK (asink);
-
- CHECK (snd_pcm_drop (alsa->handle), drop);
-
- CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
-
- CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
-
- return TRUE;
-
- /* ERRORS */
-drop:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not drop samples: %s", snd_strerror (err)));
- return FALSE;
- }
-hw_free:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not free hw params: %s", snd_strerror (err)));
- return FALSE;
- }
-non_block:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not set device to nonblocking: %s", snd_strerror (err)));
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasink_close (GstAudioSink * asink)
-{
- GstAlsaSink *alsa = GST_ALSA_SINK (asink);
- gint err;
-
- if (alsa->handle) {
- CHECK (snd_pcm_close (alsa->handle), close_error);
- alsa->handle = NULL;
- }
- gst_caps_replace (&alsa->cached_caps, NULL);
-
- return TRUE;
-
- /* ERRORS */
-close_error:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, CLOSE, (NULL),
- ("Playback close error: %s", snd_strerror (err)));
- return FALSE;
- }
-}
-
-
-/*
- * Underrun and suspend recovery
- */
-static gint
-xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err)
-{
- GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
-
- if (err == -EPIPE) { /* under-run */
- err = snd_pcm_prepare (handle);
- if (err < 0)
- GST_WARNING_OBJECT (alsa,
- "Can't recovery from underrun, prepare failed: %s",
- snd_strerror (err));
- return 0;
- } else if (err == -ESTRPIPE) {
- while ((err = snd_pcm_resume (handle)) == -EAGAIN)
- g_usleep (100); /* wait until the suspend flag is released */
-
- if (err < 0) {
- err = snd_pcm_prepare (handle);
- if (err < 0)
- GST_WARNING_OBJECT (alsa,
- "Can't recovery from suspend, prepare failed: %s",
- snd_strerror (err));
- }
- return 0;
- }
- return err;
-}
-
-static guint
-gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
-{
- GstAlsaSink *alsa;
- gint err;
- gint cptr;
- gint16 *ptr = data;
-
- alsa = GST_ALSA_SINK (asink);
-
- if (alsa->iec958 && alsa->need_swap) {
- guint i;
-
- GST_DEBUG_OBJECT (asink, "swapping bytes");
- for (i = 0; i < length / 2; i++) {
- ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
- }
- }
-
- GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);
-
- cptr = length / alsa->bytes_per_sample;
-
- GST_ALSA_SINK_LOCK (asink);
- while (cptr > 0) {
- err = snd_pcm_writei (alsa->handle, ptr, cptr);
-
- GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
- if (err < 0) {
- GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
- if (err == -EAGAIN) {
- continue;
- } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
- goto write_error;
- }
- continue;
- }
-
- ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
- cptr -= err;
- }
- GST_ALSA_SINK_UNLOCK (asink);
-
- return length - (cptr * alsa->bytes_per_sample);
-
-write_error:
- {
- GST_ALSA_SINK_UNLOCK (asink);
- return length; /* skip one period */
- }
-}
-
-static guint
-gst_alsasink_delay (GstAudioSink * asink)
-{
- GstAlsaSink *alsa;
- snd_pcm_sframes_t delay;
- int res;
-
- alsa = GST_ALSA_SINK (asink);
-
- res = snd_pcm_delay (alsa->handle, &delay);
- if (G_UNLIKELY (res < 0)) {
- /* on errors, report 0 delay */
- GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
- delay = 0;
- }
- if (G_UNLIKELY (delay < 0)) {
- /* make sure we never return a negative delay */
- GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay");
- delay = 0;
- }
-
- return delay;
-}
-
-static void
-gst_alsasink_reset (GstAudioSink * asink)
-{
- GstAlsaSink *alsa;
- gint err;
-
- alsa = GST_ALSA_SINK (asink);
-
- GST_ALSA_SINK_LOCK (asink);
- GST_DEBUG_OBJECT (alsa, "drop");
- CHECK (snd_pcm_drop (alsa->handle), drop_error);
- GST_DEBUG_OBJECT (alsa, "prepare");
- CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
- GST_DEBUG_OBJECT (alsa, "reset done");
- GST_ALSA_SINK_UNLOCK (asink);
-
- return;
-
- /* ERRORS */
-drop_error:
- {
- GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
- snd_strerror (err));
- GST_ALSA_SINK_UNLOCK (asink);
- return;
- }
-prepare_error:
- {
- GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
- snd_strerror (err));
- GST_ALSA_SINK_UNLOCK (asink);
- return;
- }
-}
--- a/gst_plugins_base/ext/alsa/gstalsasink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasink.h:
- *
- * 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 __GST_ALSASINK_H__
-#define __GST_ALSASINK_H__
-
-#include <gst/gst.h>
-#include <gst/audio/gstaudiosink.h>
-#include <alsa/asoundlib.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_ALSA_SINK (gst_alsasink_get_type())
-#define GST_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SINK,GstAlsaSink))
-#define GST_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK,GstAlsaSinkClass))
-#define GST_IS_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK))
-#define GST_IS_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK))
-#define GST_ALSA_SINK_CAST(obj) ((GstAlsaSink *) (obj))
-
-typedef struct _GstAlsaSink GstAlsaSink;
-typedef struct _GstAlsaSinkClass GstAlsaSinkClass;
-
-#define GST_ALSA_SINK_GET_LOCK(obj) (GST_ALSA_SINK_CAST (obj)->alsa_lock)
-#define GST_ALSA_SINK_LOCK(obj) (g_mutex_lock (GST_ALSA_SINK_GET_LOCK (obj)))
-#define GST_ALSA_SINK_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_SINK_GET_LOCK (obj)))
-
-/**
- * GstAlsaSink:
- *
- * Opaque data structure
- */
-struct _GstAlsaSink {
- GstAudioSink sink;
-
- gchar *device;
-
- snd_pcm_t *handle;
- snd_pcm_hw_params_t *hwparams;
- snd_pcm_sw_params_t *swparams;
-
- snd_pcm_access_t access;
- snd_pcm_format_t format;
- guint rate;
- guint channels;
- gint bytes_per_sample;
- gboolean iec958;
- gboolean need_swap;
-
- guint buffer_time;
- guint period_time;
- snd_pcm_uframes_t buffer_size;
- snd_pcm_uframes_t period_size;
-
- GstCaps *cached_caps;
-
- GMutex *alsa_lock;
-};
-
-struct _GstAlsaSinkClass {
- GstAudioSinkClass parent_class;
-};
-
-GType gst_alsasink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_ALSASINK_H__ */
--- a/gst_plugins_base/ext/alsa/gstalsasrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,881 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasrc.c:
- *
- * 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.
- */
-
-/**
- * SECTION:element-alsasrc
- * @short_description: capture audio from an alsa device
- * @see_also: alsasink, alsamixer
- *
- * <refsect2>
- * <para>
- * This element reads data from an audio card using the ALSA API.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Record from a sound card using ALSA and encode to Ogg/Vorbis.
- * </para>
- * <programlisting>
- * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <getopt.h>
-#include <alsa/asoundlib.h>
-
-#include "gstalsasrc.h"
-#include "gstalsadeviceprobe.h"
-
-#include <gst/gst-i18n-plugin.h>
-
-/* elementfactory information */
-static const GstElementDetails gst_alsasrc_details =
-GST_ELEMENT_DETAILS ("Audio source (ALSA)",
- "Source/Audio",
- "Read from a sound card via ALSA",
- "Wim Taymans <wim@fluendo.com>");
-
-#define DEFAULT_PROP_DEVICE "default"
-#define DEFAULT_PROP_DEVICE_NAME ""
-
-enum
-{
- PROP_0,
- PROP_DEVICE,
- PROP_DEVICE_NAME,
-};
-
-static void gst_alsasrc_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc,
- GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces);
-
-GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer);
-
-static void gst_alsasrc_finalize (GObject * object);
-static void gst_alsasrc_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_alsasrc_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc);
-
-static gboolean gst_alsasrc_open (GstAudioSrc * asrc);
-static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc,
- GstRingBufferSpec * spec);
-static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc);
-static gboolean gst_alsasrc_close (GstAudioSrc * asrc);
-static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length);
-static guint gst_alsasrc_delay (GstAudioSrc * asrc);
-static void gst_alsasrc_reset (GstAudioSrc * asrc);
-
-/* AlsaSrc signals and args */
-enum
-{
- LAST_SIGNAL
-};
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ALSA_SRC_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
-#else
-# define ALSA_SRC_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
-#endif
-
-static GstStaticPadTemplate alsasrc_src_factory =
- GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 32, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 32, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 24, "
- "depth = (int) 24, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
- "audio/x-raw-int, "
- "signed = (boolean) { TRUE, FALSE }, "
- "width = (int) 8, "
- "depth = (int) 8, "
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
- );
-
-static void
-gst_alsasrc_finalize (GObject * object)
-{
- GstAlsaSrc *src = GST_ALSA_SRC (object);
-
- g_free (src->device);
- g_mutex_free (src->alsa_lock);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type)
-{
- /* only support this one interface (wrapped by GstImplementsInterface) */
- g_assert (interface_type == GST_TYPE_MIXER);
-
- return gst_alsasrc_mixer_supported (this, interface_type);
-}
-
-static void
-gst_implements_interface_init (GstImplementsInterfaceClass * klass)
-{
- klass->supported = (gpointer) gst_alsasrc_interface_supported;
-}
-
-static void
-gst_alsasrc_init_interfaces (GType type)
-{
- static const GInterfaceInfo implements_iface_info = {
- (GInterfaceInitFunc) gst_implements_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo mixer_iface_info = {
- (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init,
- NULL,
- NULL,
- };
-
- g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
- &implements_iface_info);
- g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info);
-
- gst_alsa_type_add_device_property_probe_interface (type);
-}
-
-static void
-gst_alsasrc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_alsasrc_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&alsasrc_src_factory));
-}
-
-static void
-gst_alsasrc_class_init (GstAlsaSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
- GstBaseAudioSrcClass *gstbaseaudiosrc_class;
- GstAudioSrcClass *gstaudiosrc_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesrc_class = (GstBaseSrcClass *) klass;
- gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
- gstaudiosrc_class = (GstAudioSrcClass *) klass;
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_alsasrc_finalize);
- gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_alsasrc_get_property);
- gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_alsasrc_set_property);
-
- gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps);
-
- gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open);
- gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare);
- gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare);
- gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close);
- gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read);
- gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay);
- gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset);
-
- g_object_class_install_property (gobject_class, PROP_DEVICE,
- g_param_spec_string ("device", "Device",
- "ALSA device, as defined in an asound configuration file",
- DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
- g_param_spec_string ("device-name", "Device name",
- "Human-readable name of the sound device",
- DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE));
-}
-
-static void
-gst_alsasrc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstAlsaSrc *src;
-
- src = GST_ALSA_SRC (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- g_free (src->device);
- src->device = g_value_dup_string (value);
- if (src->device == NULL) {
- src->device = g_strdup (DEFAULT_PROP_DEVICE);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_alsasrc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstAlsaSrc *src;
-
- src = GST_ALSA_SRC (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- g_value_set_string (value, src->device);
- break;
- case PROP_DEVICE_NAME:
- g_value_take_string (value,
- gst_alsa_find_device_name (GST_OBJECT_CAST (src),
- src->device, src->handle, SND_PCM_STREAM_CAPTURE));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class)
-{
- GST_DEBUG_OBJECT (alsasrc, "initializing");
-
- alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE);
- alsasrc->cached_caps = NULL;
-
- alsasrc->alsa_lock = g_mutex_new ();
-}
-
-#define CHECK(call, error) \
-G_STMT_START { \
-if ((err = call) < 0) \
- goto error; \
-} G_STMT_END;
-
-
-static GstCaps *
-gst_alsasrc_getcaps (GstBaseSrc * bsrc)
-{
- GstElementClass *element_class;
- GstPadTemplate *pad_template;
- GstAlsaSrc *src;
- GstCaps *caps;
-
- src = GST_ALSA_SRC (bsrc);
-
- if (src->handle == NULL) {
- GST_DEBUG_OBJECT (src, "device not open, using template caps");
- return NULL; /* base class will get template caps for us */
- }
-
- if (src->cached_caps) {
- GST_LOG_OBJECT (src, "Returning cached caps");
- return gst_caps_ref (src->cached_caps);
- }
-
- element_class = GST_ELEMENT_GET_CLASS (src);
- pad_template = gst_element_class_get_pad_template (element_class, "src");
- g_return_val_if_fail (pad_template != NULL, NULL);
-
- caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle,
- gst_pad_template_get_caps (pad_template));
-
- if (caps) {
- src->cached_caps = gst_caps_ref (caps);
- }
-
- GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps);
-
- return caps;
-}
-
-static int
-set_hwparams (GstAlsaSrc * alsa)
-{
- guint rrate;
- gint err, dir;
- snd_pcm_hw_params_t *params;
-
- snd_pcm_hw_params_malloc (¶ms);
-
- /* choose all parameters */
- CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config);
- /* set the interleaved read/write format */
- CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access),
- wrong_access);
- /* set the sample format */
- CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format),
- no_sample_format);
- /* set the count of channels */
- CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels),
- no_channels);
- /* set the stream rate */
- rrate = alsa->rate;
- CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL),
- no_rate);
- if (rrate != alsa->rate)
- goto rate_match;
-
- if (alsa->buffer_time != -1) {
- /* set the buffer time */
- CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params,
- &alsa->buffer_time, &dir), buffer_time);
- }
- if (alsa->period_time != -1) {
- /* set the period time */
- CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params,
- &alsa->period_time, &dir), period_time);
- }
-
- /* write the parameters to device */
- CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params);
-
- CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size),
- buffer_size);
-
- CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, &dir),
- period_size);
-
- snd_pcm_hw_params_free (params);
- return 0;
-
- /* ERRORS */
-no_config:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Broken configuration for recording: no configurations available: %s",
- snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-wrong_access:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Access type not available for recording: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_sample_format:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Sample format not available for recording: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_channels:
- {
- gchar *msg = NULL;
-
- if ((alsa->channels) == 1)
- msg = g_strdup (_("Could not open device for recording in mono mode."));
- if ((alsa->channels) == 2)
- msg = g_strdup (_("Could not open device for recording in stereo mode."));
- if ((alsa->channels) > 2)
- msg =
- g_strdup_printf (_
- ("Could not open device for recording in %d-channel mode"),
- alsa->channels);
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (msg), (snd_strerror (err)));
- g_free (msg);
- snd_pcm_hw_params_free (params);
- return err;
- }
-no_rate:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Rate %iHz not available for recording: %s",
- alsa->rate, snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-rate_match:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err));
- snd_pcm_hw_params_free (params);
- return -EINVAL;
- }
-buffer_time:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set buffer time %i for recording: %s",
- alsa->buffer_time, snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-buffer_size:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to get buffer size for recording: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-period_time:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set period time %i for recording: %s", alsa->period_time,
- snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-period_size:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to get period size for recording: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-set_hw_params:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set hw params for recording: %s", snd_strerror (err)));
- snd_pcm_hw_params_free (params);
- return err;
- }
-}
-
-static int
-set_swparams (GstAlsaSrc * alsa)
-{
- int err;
- snd_pcm_sw_params_t *params;
-
- snd_pcm_sw_params_malloc (¶ms);
-
- /* get the current swparams */
- CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config);
- /* allow the transfer when at least period_size samples can be processed */
- CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params,
- alsa->period_size), set_avail);
- /* start the transfer on first read */
- CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params,
- 0), start_threshold);
-
-#if GST_CHECK_ALSA_VERSION(1,0,16)
- /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */
-#else
- /* align all transfers to 1 sample */
- CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align);
-#endif
-
- /* write the parameters to the recording device */
- CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params);
-
- snd_pcm_sw_params_free (params);
- return 0;
-
- /* ERRORS */
-no_config:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to determine current swparams for playback: %s",
- snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-start_threshold:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set start threshold mode for playback: %s",
- snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-set_avail:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set avail min for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-#if !GST_CHECK_ALSA_VERSION(1,0,16)
-set_align:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set transfer align for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-#endif
-set_sw_params:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Unable to set sw params for playback: %s", snd_strerror (err)));
- snd_pcm_sw_params_free (params);
- return err;
- }
-}
-
-static gboolean
-alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec)
-{
- switch (spec->type) {
- case GST_BUFTYPE_LINEAR:
- alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width,
- spec->sign ? 0 : 1, spec->bigend ? 1 : 0);
- break;
- case GST_BUFTYPE_FLOAT:
- switch (spec->format) {
- case GST_FLOAT32_LE:
- alsa->format = SND_PCM_FORMAT_FLOAT_LE;
- break;
- case GST_FLOAT32_BE:
- alsa->format = SND_PCM_FORMAT_FLOAT_BE;
- break;
- case GST_FLOAT64_LE:
- alsa->format = SND_PCM_FORMAT_FLOAT64_LE;
- break;
- case GST_FLOAT64_BE:
- alsa->format = SND_PCM_FORMAT_FLOAT64_BE;
- break;
- default:
- goto error;
- }
- break;
- case GST_BUFTYPE_A_LAW:
- alsa->format = SND_PCM_FORMAT_A_LAW;
- break;
- case GST_BUFTYPE_MU_LAW:
- alsa->format = SND_PCM_FORMAT_MU_LAW;
- break;
- default:
- goto error;
-
- }
- alsa->rate = spec->rate;
- alsa->channels = spec->channels;
- alsa->buffer_time = spec->buffer_time;
- alsa->period_time = spec->latency_time;
- alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
-
- return TRUE;
-
- /* ERRORS */
-error:
- {
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasrc_open (GstAudioSrc * asrc)
-{
- GstAlsaSrc *alsa;
- gint err;
-
- alsa = GST_ALSA_SRC (asrc);
-
- CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE,
- SND_PCM_NONBLOCK), open_error);
-
- if (!alsa->mixer)
- alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE);
-
- return TRUE;
-
- /* ERRORS */
-open_error:
- {
- if (err == -EBUSY) {
- GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY,
- (_("Could not open audio device for recording. "
- "Device is being used by another application.")),
- ("Device '%s' is busy", alsa->device));
- } else {
- GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ,
- (_("Could not open audio device for recording.")),
- ("Recording open error on device '%s': %s", alsa->device,
- snd_strerror (err)));
- }
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
-{
- GstAlsaSrc *alsa;
- gint err;
-
- alsa = GST_ALSA_SRC (asrc);
-
- if (!alsasrc_parse_spec (alsa, spec))
- goto spec_parse;
-
- CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block);
-
- CHECK (set_hwparams (alsa), hw_params_failed);
- CHECK (set_swparams (alsa), sw_params_failed);
- CHECK (snd_pcm_prepare (alsa->handle), prepare_failed);
-
- alsa->bytes_per_sample = spec->bytes_per_sample;
- spec->segsize = alsa->period_size * spec->bytes_per_sample;
- spec->segtotal = alsa->buffer_size / alsa->period_size;
- spec->silence_sample[0] = 0;
- spec->silence_sample[1] = 0;
- spec->silence_sample[2] = 0;
- spec->silence_sample[3] = 0;
-
- return TRUE;
-
- /* ERRORS */
-spec_parse:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Error parsing spec"));
- return FALSE;
- }
-non_block:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not set device to blocking: %s", snd_strerror (err)));
- return FALSE;
- }
-hw_params_failed:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Setting of hwparams failed: %s", snd_strerror (err)));
- return FALSE;
- }
-sw_params_failed:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Setting of swparams failed: %s", snd_strerror (err)));
- return FALSE;
- }
-prepare_failed:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Prepare failed: %s", snd_strerror (err)));
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasrc_unprepare (GstAudioSrc * asrc)
-{
- GstAlsaSrc *alsa;
- gint err;
-
- alsa = GST_ALSA_SRC (asrc);
-
- CHECK (snd_pcm_drop (alsa->handle), drop);
-
- CHECK (snd_pcm_hw_free (alsa->handle), hw_free);
-
- CHECK (snd_pcm_nonblock (alsa->handle, 1), non_block);
-
- return TRUE;
-
- /* ERRORS */
-drop:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not drop samples: %s", snd_strerror (err)));
- return FALSE;
- }
-hw_free:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not free hw params: %s", snd_strerror (err)));
- return FALSE;
- }
-non_block:
- {
- GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL),
- ("Could not set device to nonblocking: %s", snd_strerror (err)));
- return FALSE;
- }
-}
-
-static gboolean
-gst_alsasrc_close (GstAudioSrc * asrc)
-{
- GstAlsaSrc *alsa = GST_ALSA_SRC (asrc);
-
- snd_pcm_close (alsa->handle);
-
- if (alsa->mixer) {
- gst_alsa_mixer_free (alsa->mixer);
- alsa->mixer = NULL;
- }
-
- gst_caps_replace (&alsa->cached_caps, NULL);
-
- return TRUE;
-}
-
-/*
- * Underrun and suspend recovery
- */
-static gint
-xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err)
-{
- GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err);
-
- if (err == -EPIPE) { /* under-run */
- err = snd_pcm_prepare (handle);
- if (err < 0)
- GST_WARNING_OBJECT (alsa,
- "Can't recovery from underrun, prepare failed: %s",
- snd_strerror (err));
- return 0;
- } else if (err == -ESTRPIPE) {
- while ((err = snd_pcm_resume (handle)) == -EAGAIN)
- g_usleep (100); /* wait until the suspend flag is released */
-
- if (err < 0) {
- err = snd_pcm_prepare (handle);
- if (err < 0)
- GST_WARNING_OBJECT (alsa,
- "Can't recovery from suspend, prepare failed: %s",
- snd_strerror (err));
- }
- return 0;
- }
- return err;
-}
-
-static guint
-gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length)
-{
- GstAlsaSrc *alsa;
- gint err;
- gint cptr;
- gint16 *ptr;
-
- alsa = GST_ALSA_SRC (asrc);
-
- cptr = length / alsa->bytes_per_sample;
- ptr = data;
-
- GST_ALSA_SRC_LOCK (asrc);
- while (cptr > 0) {
- if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) {
- if (err == -EAGAIN) {
- GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
- continue;
- } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
- goto read_error;
- }
- continue;
- }
-
- ptr += err * alsa->channels;
- cptr -= err;
- }
- GST_ALSA_SRC_UNLOCK (asrc);
-
- return length - cptr;
-
-read_error:
- {
- GST_ALSA_SRC_UNLOCK (asrc);
- return length; /* skip one period */
- }
-}
-
-static guint
-gst_alsasrc_delay (GstAudioSrc * asrc)
-{
- GstAlsaSrc *alsa;
- snd_pcm_sframes_t delay;
- int res;
-
- alsa = GST_ALSA_SRC (asrc);
-
- res = snd_pcm_delay (alsa->handle, &delay);
- if (G_UNLIKELY (res < 0)) {
- GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res);
- delay = 0;
- }
-
- return CLAMP (delay, 0, alsa->buffer_size);
-}
-
-static void
-gst_alsasrc_reset (GstAudioSrc * asrc)
-{
- GstAlsaSrc *alsa;
- gint err;
-
- alsa = GST_ALSA_SRC (asrc);
-
- GST_ALSA_SRC_LOCK (asrc);
- GST_DEBUG_OBJECT (alsa, "drop");
- CHECK (snd_pcm_drop (alsa->handle), drop_error);
- GST_DEBUG_OBJECT (alsa, "prepare");
- CHECK (snd_pcm_prepare (alsa->handle), prepare_error);
- GST_DEBUG_OBJECT (alsa, "reset done");
- GST_ALSA_SRC_UNLOCK (asrc);
-
- return;
-
- /* ERRORS */
-drop_error:
- {
- GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s",
- snd_strerror (err));
- GST_ALSA_SRC_UNLOCK (asrc);
- return;
- }
-prepare_error:
- {
- GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s",
- snd_strerror (err));
- GST_ALSA_SRC_UNLOCK (asrc);
- return;
- }
-}
--- a/gst_plugins_base/ext/alsa/gstalsasrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
- *
- * gstalsasrc.h:
- *
- * 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 __GST_ALSASRC_H__
-#define __GST_ALSASRC_H__
-
-#include <gst/audio/gstaudiosrc.h>
-#include "gstalsa.h"
-#include "gstalsamixer.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_ALSA_SRC (gst_alsasrc_get_type())
-#define GST_ALSA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SRC,GstAlsaSrc))
-#define GST_ALSA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SRC,GstAlsaSrcClass))
-#define GST_IS_ALSA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SRC))
-#define GST_IS_ALSA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SRC))
-#define GST_ALSA_SRC_CAST(obj) ((GstAlsaSrc *)(obj))
-
-#define GST_ALSA_SRC_GET_LOCK(obj) (GST_ALSA_SRC_CAST (obj)->alsa_lock)
-#define GST_ALSA_SRC_LOCK(obj) (g_mutex_lock (GST_ALSA_SRC_GET_LOCK (obj)))
-#define GST_ALSA_SRC_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_SRC_GET_LOCK (obj)))
-
-typedef struct _GstAlsaSrc GstAlsaSrc;
-typedef struct _GstAlsaSrcClass GstAlsaSrcClass;
-
-/**
- * GstAlsaSrc:
- *
- * Opaque data structure
- */
-struct _GstAlsaSrc {
- GstAudioSrc src;
-
- gchar *device;
-
- snd_pcm_t *handle;
- snd_pcm_hw_params_t *hwparams;
- snd_pcm_sw_params_t *swparams;
-
- GstCaps *cached_caps;
-
- snd_pcm_access_t access;
- snd_pcm_format_t format;
- guint rate;
- guint channels;
- gint bytes_per_sample;
-
- guint buffer_time;
- guint period_time;
- snd_pcm_uframes_t buffer_size;
- snd_pcm_uframes_t period_size;
-
- GstAlsaMixer *mixer;
-
- GMutex *alsa_lock;
-};
-
-struct _GstAlsaSrcClass {
- GstAudioSrcClass parent_class;
-};
-
-GType gst_alsasrc_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_ALSASRC_H__ */
--- a/gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,490 +0,0 @@
-/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * <2005> Wim Taymans <wim@fluendo.com>
- * <2005> 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <errno.h>
-
-#include "gstcdparanoiasrc.h"
-#include "gst/gst-i18n-plugin.h"
-
-enum
-{
- TRANSPORT_ERROR,
- UNCORRECTED_ERROR,
- NUM_SIGNALS
-};
-
-enum
-{
- PROP_0,
- PROP_READ_SPEED,
- PROP_PARANOIA_MODE,
- PROP_SEARCH_OVERLAP,
- PROP_GENERIC_DEVICE
-};
-
-#define DEFAULT_READ_SPEED -1
-#define DEFAULT_SEARCH_OVERLAP -1
-#define DEFAULT_PARANOIA_MODE PARANOIA_MODE_FRAGMENT
-#define DEFAULT_GENERIC_DEVICE NULL
-
-GST_DEBUG_CATEGORY_STATIC (gst_cd_paranoia_src_debug);
-#define GST_CAT_DEFAULT gst_cd_paranoia_src_debug
-
-GST_BOILERPLATE (GstCdParanoiaSrc, gst_cd_paranoia_src, GstCddaBaseSrc,
- GST_TYPE_CDDA_BASE_SRC);
-
-static void gst_cd_paranoia_src_finalize (GObject * obj);
-static void gst_cd_paranoia_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void gst_cd_paranoia_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static GstBuffer *gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * src,
- gint sector);
-static gboolean gst_cd_paranoia_src_open (GstCddaBaseSrc * src,
- const gchar * device);
-static void gst_cd_paranoia_src_close (GstCddaBaseSrc * src);
-
-static const GstElementDetails cdparanoia_details =
-GST_ELEMENT_DETAILS ("CD Audio (cdda) Source, Paranoia IV",
- "Source/File",
- "Read audio from CD in paranoid mode",
- "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>");
-
-/* We use these to serialize calls to paranoia_read() among several
- * cdparanoiasrc instances. We do this because it's the only reasonably
- * easy way to find out the calling object from within the paranoia
- * callback, and we need the object instance in there to emit our signals */
-static GstCdParanoiaSrc *cur_cb_source;
-static GStaticMutex cur_cb_mutex = G_STATIC_MUTEX_INIT;
-
-static gint cdpsrc_signals[NUM_SIGNALS]; /* all 0 */
-
-#define GST_TYPE_CD_PARANOIA_MODE (gst_cd_paranoia_mode_get_type())
-static GType
-gst_cd_paranoia_mode_get_type (void)
-{
- static const GFlagsValue paranoia_modes[] = {
- {PARANOIA_MODE_DISABLE, "PARANOIA_MODE_DISABLE", "disable"},
- {PARANOIA_MODE_FRAGMENT, "PARANOIA_MODE_FRAGMENT", "fragment"},
- {PARANOIA_MODE_OVERLAP, "PARANOIA_MODE_OVERLAP", "overlap"},
- {PARANOIA_MODE_SCRATCH, "PARANOIA_MODE_SCRATCH", "scratch"},
- {PARANOIA_MODE_REPAIR, "PARANOIA_MODE_REPAIR", "repair"},
- {PARANOIA_MODE_FULL, "PARANOIA_MODE_FULL", "full"},
- {0, NULL, NULL},
- };
-
- static GType type; /* 0 */
-
- if (!type) {
- type = g_flags_register_static ("GstCdParanoiaMode", paranoia_modes);
- }
-
- return type;
-}
-
-static void
-gst_cd_paranoia_src_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &cdparanoia_details);
-}
-
-static void
-gst_cd_paranoia_src_init (GstCdParanoiaSrc * src, GstCdParanoiaSrcClass * klass)
-{
- src->d = NULL;
- src->p = NULL;
- src->next_sector = -1;
-
- src->search_overlap = DEFAULT_SEARCH_OVERLAP;
- src->paranoia_mode = DEFAULT_PARANOIA_MODE;
- src->read_speed = DEFAULT_READ_SPEED;
- src->generic_device = g_strdup (DEFAULT_GENERIC_DEVICE);
-}
-
-static void
-gst_cd_paranoia_src_class_init (GstCdParanoiaSrcClass * klass)
-{
- GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->set_property = gst_cd_paranoia_src_set_property;
- gobject_class->get_property = gst_cd_paranoia_src_get_property;
- gobject_class->finalize = gst_cd_paranoia_src_finalize;
-
- cddabasesrc_class->open = gst_cd_paranoia_src_open;
- cddabasesrc_class->close = gst_cd_paranoia_src_close;
- cddabasesrc_class->read_sector = gst_cd_paranoia_src_read_sector;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GENERIC_DEVICE,
- g_param_spec_string ("generic-device", "Generic device",
- "Use specified generic scsi device", DEFAULT_GENERIC_DEVICE,
- G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED,
- g_param_spec_int ("read-speed", "Read speed",
- "Read from device at specified speed", -1, G_MAXINT,
- DEFAULT_READ_SPEED, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARANOIA_MODE,
- g_param_spec_flags ("paranoia-mode", "Paranoia mode",
- "Type of checking to perform", GST_TYPE_CD_PARANOIA_MODE,
- DEFAULT_PARANOIA_MODE, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH_OVERLAP,
- g_param_spec_int ("search-overlap", "Search overlap",
- "Force minimum overlap search during verification to n sectors", -1,
- 75, DEFAULT_SEARCH_OVERLAP, G_PARAM_READWRITE));
-
- /* FIXME: we don't really want signals for this, but messages on the bus,
- * but then we can't check any longer whether anyone is interested in them */
- cdpsrc_signals[TRANSPORT_ERROR] =
- g_signal_new ("transport-error", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstCdParanoiaSrcClass, transport_error),
- NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
- cdpsrc_signals[UNCORRECTED_ERROR] =
- g_signal_new ("uncorrected-error", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GstCdParanoiaSrcClass, uncorrected_error),
- NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
-}
-
-static gboolean
-gst_cd_paranoia_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
- gint i;
-
- GST_DEBUG_OBJECT (src, "trying to open device %s (generic-device=%s) ...",
- device, GST_STR_NULL (src->generic_device));
-
- /* find the device */
- if (src->generic_device != NULL) {
- src->d = cdda_identify_scsi (src->generic_device, device, FALSE, NULL);
- } else {
- if (device != NULL) {
- src->d = cdda_identify (device, FALSE, NULL);
- } else {
- src->d = cdda_identify ("/dev/cdrom", FALSE, NULL);
- }
- }
-
- /* fail if the device couldn't be found */
- if (src->d == NULL)
- goto no_device;
-
- /* set verbosity mode */
- cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);
-
- /* open the disc */
- if (cdda_open (src->d))
- goto open_failed;
-
- if (src->read_speed != -1) {
- cdda_speed_set (src->d, src->read_speed);
- }
-
- for (i = 1; i < src->d->tracks + 1; i++) {
- GstCddaBaseSrcTrack track = { 0, };
-
- track.num = i;
- track.is_audio = IS_AUDIO (src->d, i - 1);
- track.start = cdda_track_firstsector (src->d, i);
- track.end = cdda_track_lastsector (src->d, i);
- track.tags = NULL;
-
- gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track);
- }
-
- /* create the paranoia struct and set it up */
- src->p = paranoia_init (src->d);
- if (src->p == NULL)
- goto init_failed;
-
- paranoia_modeset (src->p, src->paranoia_mode);
-
- if (src->search_overlap != -1)
- paranoia_overlapset (src->p, src->search_overlap);
-
- src->next_sector = -1;
-
- return TRUE;
-
- /* ERRORS */
-no_device:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
- (_("Could not open CD device for reading.")), ("cdda_identify failed"));
- return FALSE;
- }
-open_failed:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
- (_("Could not open CD device for reading.")), ("cdda_open failed"));
- cdda_close (src->d);
- src->d = NULL;
- return FALSE;
- }
-init_failed:
- {
- GST_ELEMENT_ERROR (src, LIBRARY, INIT,
- ("failed to initialize paranoia"), ("failed to initialize paranoia"));
- return FALSE;
- }
-}
-
-static void
-gst_cd_paranoia_src_close (GstCddaBaseSrc * cddabasesrc)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
-
- if (src->p) {
- paranoia_free (src->p);
- src->p = NULL;
- }
-
- if (src->d) {
- cdda_close (src->d);
- src->d = NULL;
- }
-
- src->next_sector = -1;
-}
-
-static void
-gst_cd_paranoia_dummy_callback (long inpos, int function)
-{
- /* Used by instanced where no one is interested what's happening here */
-}
-
-static void
-gst_cd_paranoia_paranoia_callback (long inpos, int function)
-{
- GstCdParanoiaSrc *src = cur_cb_source;
- gint sector = (gint) (inpos / CD_FRAMEWORDS);
-
- switch (function) {
- case PARANOIA_CB_SKIP:
- GST_INFO_OBJECT (src, "Skip at sector %d", sector);
- g_signal_emit (src, cdpsrc_signals[UNCORRECTED_ERROR], 0, sector);
- break;
- case PARANOIA_CB_READERR:
- GST_INFO_OBJECT (src, "Transport error at sector %d", sector);
- g_signal_emit (src, cdpsrc_signals[TRANSPORT_ERROR], 0, sector);
- break;
- default:
- break;
- }
-}
-
-static gboolean
-gst_cd_paranoia_src_signal_is_being_watched (GstCdParanoiaSrc * src, gint sig)
-{
- return g_signal_has_handler_pending (src, cdpsrc_signals[sig], 0, FALSE);
-}
-
-static GstBuffer *
-gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc);
- GstBuffer *buf;
- gboolean do_serialize;
- gint16 *cdda_buf;
-
-#if 0
- /* Do we really need to output this? (tpm) */
- /* Due to possible autocorrections of start sectors of audio tracks on
- * multisession cds, we can maybe not compute the correct discid.
- * So issue a warning.
- * See cdparanoia/interface/common-interface.c:FixupTOC */
- if (src->d && src->d->cd_extra) {
- g_message
- ("DiscID on multisession discs might be broken. Use at own risk.");
- }
-#endif
-
- if (src->next_sector == -1 || src->next_sector != sector) {
- if (paranoia_seek (src->p, sector, SEEK_SET) == -1)
- goto seek_failed;
-
- GST_DEBUG_OBJECT (src, "successfully seeked to sector %d", sector);
- src->next_sector = sector;
- }
-
- do_serialize =
- gst_cd_paranoia_src_signal_is_being_watched (src, TRANSPORT_ERROR) ||
- gst_cd_paranoia_src_signal_is_being_watched (src, UNCORRECTED_ERROR);
-
- if (do_serialize) {
- GST_LOG_OBJECT (src, "Signal handlers connected, serialising access");
- g_static_mutex_lock (&cur_cb_mutex);
- GST_LOG_OBJECT (src, "Got lock");
- cur_cb_source = src;
-
- cdda_buf = paranoia_read (src->p, gst_cd_paranoia_paranoia_callback);
-
- cur_cb_source = NULL;
- GST_LOG_OBJECT (src, "Releasing lock");
- g_static_mutex_unlock (&cur_cb_mutex);
- } else {
- cdda_buf = paranoia_read (src->p, gst_cd_paranoia_dummy_callback);
- }
-
- if (cdda_buf == NULL)
- goto read_failed;
-
- buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW);
- memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW);
-
- /* cdda base class will take care of timestamping etc. */
- ++src->next_sector;
-
- return buf;
-
- /* ERRORS */
-seek_failed:
- {
- GST_WARNING_OBJECT (src, "seek to sector %d failed!", sector);
- GST_ELEMENT_ERROR (src, RESOURCE, SEEK,
- (_("Could not seek CD.")),
- ("paranoia_seek to %d failed: %s", sector, g_strerror (errno)));
- return NULL;
- }
-read_failed:
- {
- GST_WARNING_OBJECT (src, "read at sector %d failed!", sector);
- GST_ELEMENT_ERROR (src, RESOURCE, READ,
- (_("Could not read CD.")),
- ("paranoia_read at %d failed: %s", sector, g_strerror (errno)));
- return NULL;
- }
-}
-
-static void
-gst_cd_paranoia_src_finalize (GObject * obj)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (obj);
-
- g_free (src->generic_device);
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_cd_paranoia_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object);
-
- GST_OBJECT_LOCK (src);
-
- switch (prop_id) {
- case PROP_GENERIC_DEVICE:{
- g_free (src->generic_device);
- src->generic_device = g_value_dup_string (value);
- if (src->generic_device && src->generic_device[0] == '\0') {
- g_free (src->generic_device);
- src->generic_device = NULL;
- }
- break;
- }
- case PROP_READ_SPEED:{
- src->read_speed = g_value_get_int (value);
- if (src->read_speed == 0)
- src->read_speed = -1;
- break;
- }
- case PROP_PARANOIA_MODE:{
- src->paranoia_mode = g_value_get_flags (value) & PARANOIA_MODE_FULL;
- break;
- }
- case PROP_SEARCH_OVERLAP:{
- src->search_overlap = g_value_get_int (value);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- GST_OBJECT_UNLOCK (src);
-}
-
-static void
-gst_cd_paranoia_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object);
-
- GST_OBJECT_LOCK (src);
-
- switch (prop_id) {
- case PROP_READ_SPEED:
- g_value_set_int (value, src->read_speed);
- break;
- case PROP_PARANOIA_MODE:
- g_value_set_flags (value, src->paranoia_mode);
- break;
- case PROP_GENERIC_DEVICE:
- g_value_set_string (value, src->generic_device);
- break;
- case PROP_SEARCH_OVERLAP:
- g_value_set_int (value, src->search_overlap);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- GST_OBJECT_UNLOCK (src);
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_cd_paranoia_src_debug, "cdparanoiasrc", 0,
- "CD Paranoia Source");
-
- if (!gst_element_register (plugin, "cdparanoiasrc", GST_RANK_SECONDARY,
- GST_TYPE_CD_PARANOIA_SRC))
- return FALSE;
-
-#ifdef ENABLE_NLS
- GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
- LOCALEDIR);
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
-
- return TRUE;
-}
-
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "cdparanoia",
- "Read audio from CD in paranoid mode",
- plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/cdparanoia/gstcdparanoiasrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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 __GST_CD_PARANOIA_SRC_H__
-#define __GST_CD_PARANOIA_SRC_H__
-
-#include "gst/cdda/gstcddabasesrc.h"
-
-G_BEGIN_DECLS
-
-#define size16 gint16
-#define size32 gint32
-
-#ifdef CDPARANOIA_HEADERS_IN_DIR
- #include <cdda/cdda_interface.h>
- #include <cdda/cdda_paranoia.h>
-#else
- #include <cdda_interface.h>
- #include <cdda_paranoia.h>
-#endif
-
-#define GST_TYPE_CD_PARANOIA_SRC (gst_cd_paranoia_src_get_type())
-#define GST_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrc))
-#define GST_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrcClass))
-#define GST_IS_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_PARANOIA_SRC))
-#define GST_IS_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_PARANOIA_SRC))
-#define GST_CD_PARANOIA_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdParanoiaSrcClass))
-
-typedef struct _GstCdParanoiaSrc GstCdParanoiaSrc;
-typedef struct _GstCdParanoiaSrcClass GstCdParanoiaSrcClass;
-
-/**
- * GstCdParanoiaSrc:
- *
- * The cdparanoia object structure.
- */
-struct _GstCdParanoiaSrc {
- GstCddaBaseSrc cddabasesrc;
-
- /*< private >*/
- cdrom_drive *d;
- cdrom_paranoia *p;
-
- gint next_sector; /* -1 or next sector we expect to
- * read, so we know when to do a seek */
-
- gint paranoia_mode;
- gint read_speed;
- gint search_overlap;
-
- gchar *generic_device;
-};
-
-struct _GstCdParanoiaSrcClass {
- GstCddaBaseSrcClass parent_class;
-
- /* signal callbacks */
- /**
- * GstCdParanoiaSrcClass::transport-error:
- * @src: the GstCddaBaseSrc source element object
- * @sector: the sector at which the error happened
- *
- * This signal is emitted when a sector could not be read
- * because of a transport error.
- */
- void (*transport_error) (GstCdParanoiaSrc * src, gint sector);
- /**
- * GstCdParanoiaSrcClass::uncorrected-error:
- * @src: the GstCddaBaseSrc source element object
- * @sector: the sector at which the error happened
- *
- * This signal is emitted when a sector could not be read
- * because of a transport error.
- */
- void (*uncorrected_error) (GstCdParanoiaSrc * src, gint sector);
-};
-
-GType gst_cd_paranoia_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_CD_PARANOIA_SRC_H__ */
-
--- a/gst_plugins_base/ext/gio/gstgio.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 "gstgio.h"
-#include "gstgiosink.h"
-#include "gstgiosrc.h"
-#include "gstgiostreamsink.h"
-#include "gstgiostreamsrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_debug);
-#define GST_CAT_DEFAULT gst_gio_debug
-
-/* @func_name: Name of the GIO function, for debugging messages.
- * @err: Error location. *err may be NULL, but err must be non-NULL.
- * @ret: Flow return location. May be NULL. Is set to either #GST_FLOW_ERROR
- * or #GST_FLOW_WRONG_STATE.
- *
- * Returns: TRUE to indicate a handled error. Error at given location err will
- * be freed and *err will be set to NULL. A FALSE return indicates an unhandled
- * error: The err location is unchanged and guaranteed to be != NULL. ret, if
- * given, is set to GST_FLOW_ERROR.
- */
-gboolean
-gst_gio_error (gpointer element, const gchar * func_name, GError ** err,
- GstFlowReturn * ret)
-{
- gboolean handled = TRUE;
-
- if (ret)
- *ret = GST_FLOW_ERROR;
-
- if (GST_GIO_ERROR_MATCHES (*err, CANCELLED)) {
- GST_DEBUG_OBJECT (element, "blocking I/O call cancelled (%s)", func_name);
- if (ret)
- *ret = GST_FLOW_WRONG_STATE;
- } else if (*err != NULL) {
- handled = FALSE;
- } else {
- GST_ELEMENT_ERROR (element, LIBRARY, FAILED, (NULL),
- ("%s call failed without error set", func_name));
- }
-
- if (handled)
- g_clear_error (err);
-
- return handled;
-}
-
-GstFlowReturn
-gst_gio_seek (gpointer element, GSeekable * stream, guint64 offset,
- GCancellable * cancel)
-{
- gboolean success;
- GstFlowReturn ret;
- GError *err = NULL;
-
- GST_LOG_OBJECT (element, "seeking to offset %" G_GINT64_FORMAT, offset);
-
- success = g_seekable_seek (stream, offset, G_SEEK_SET, cancel, &err);
-
- if (success)
- ret = GST_FLOW_OK;
- else if (!gst_gio_error (element, "g_seekable_seek", &err, &ret)) {
- GST_ELEMENT_ERROR (element, RESOURCE, SEEK, (NULL),
- ("Could not seek: %s", err->message));
- g_clear_error (&err);
- }
-
- return ret;
-}
-
-static gchar **
-gst_gio_get_supported_protocols (void)
-{
- return g_strdupv ((gchar **)
- g_vfs_get_supported_uri_schemes (g_vfs_get_default ()));
-}
-
-static GstURIType
-gst_gio_uri_handler_get_type_sink (void)
-{
- return GST_URI_SINK;
-}
-
-static GstURIType
-gst_gio_uri_handler_get_type_src (void)
-{
- return GST_URI_SRC;
-}
-
-static gchar **
-gst_gio_uri_handler_get_protocols (void)
-{
- static gchar **protocols = NULL;
-
- if (!protocols)
- protocols = gst_gio_get_supported_protocols ();
-
- return protocols;
-}
-
-static const gchar *
-gst_gio_uri_handler_get_uri (GstURIHandler * handler)
-{
- GstElement *element = GST_ELEMENT (handler);
- const gchar *uri;
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
-
- g_object_get (G_OBJECT (element), "location", &uri, NULL);
-
- return uri;
-}
-
-static gboolean
-gst_gio_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri)
-{
- GstElement *element = GST_ELEMENT (handler);
-
- g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
-
- if (GST_STATE (element) == GST_STATE_PLAYING ||
- GST_STATE (element) == GST_STATE_PAUSED)
- return FALSE;
-
- g_object_set (G_OBJECT (element), "location", uri, NULL);
-
- return TRUE;
-}
-
-static void
-gst_gio_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
- GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
- gboolean sink = GPOINTER_TO_INT (iface_data); /* See in do_init below. */
-
- if (sink)
- iface->get_type = gst_gio_uri_handler_get_type_sink;
- else
- iface->get_type = gst_gio_uri_handler_get_type_src;
- iface->get_protocols = gst_gio_uri_handler_get_protocols;
- iface->get_uri = gst_gio_uri_handler_get_uri;
- iface->set_uri = gst_gio_uri_handler_set_uri;
-}
-
-void
-gst_gio_uri_handler_do_init (GType type)
-{
- GInterfaceInfo uri_handler_info = {
- gst_gio_uri_handler_init,
- NULL,
- NULL
- };
-
- /* Store information for uri_handler_init to use for distinguishing the
- * element types. This lets us use a single interface implementation for both
- * classes. */
- uri_handler_info.interface_data = GINT_TO_POINTER (g_type_is_a (type,
- GST_TYPE_BASE_SINK));
-
- g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_handler_info);
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- gboolean ret = TRUE;
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_debug, "gio", 0, "GIO elements");
-
- /* FIXME: Rank is MARGINAL for now, should be at least SECONDARY+1 in the future
- * to replace gnomevfssink/src. For testing purposes PRIMARY+1 one makes sense
- * so it gets autoplugged and preferred over filesrc/sink. */
-
- ret &= gst_element_register (plugin, "giosink", GST_RANK_MARGINAL,
- GST_TYPE_GIO_SINK);
-
- ret &= gst_element_register (plugin, "giosrc", GST_RANK_MARGINAL,
- GST_TYPE_GIO_SRC);
-
- ret &= gst_element_register (plugin, "giostreamsink", GST_RANK_NONE,
- GST_TYPE_GIO_STREAM_SINK);
-
- ret &= gst_element_register (plugin, "giostreamsrc", GST_RANK_NONE,
- GST_TYPE_GIO_STREAM_SRC);
-
- return ret;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "gio",
- "GIO elements", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
- GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/gio/gstgio.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_H__
-#define __GST_GIO_H__
-
-#include <gio/gio.h>
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_GIO_ERROR_MATCHES(err, code) g_error_matches (err, G_IO_ERROR, G_IO_ERROR_##code)
-
-#define GST_GIO_STREAM_IS_SEEKABLE(stream) (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)))
-
-gboolean gst_gio_error (gpointer element, const gchar *func_name,
- GError **err, GstFlowReturn *ret);
-GstFlowReturn gst_gio_seek (gpointer element, GSeekable *stream, guint64 offset,
- GCancellable *cancel);
-void gst_gio_uri_handler_do_init (GType type);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_H__ */
--- a/gst_plugins_base/ext/gio/gstgiobasesink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 "gstgiobasesink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_base_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_base_sink_debug
-
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-GST_BOILERPLATE (GstGioBaseSink, gst_gio_base_sink, GstBaseSink,
- GST_TYPE_BASE_SINK);
-
-static void gst_gio_base_sink_finalize (GObject * object);
-static gboolean gst_gio_base_sink_start (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_stop (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_unlock (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink);
-static gboolean gst_gio_base_sink_event (GstBaseSink * base_sink,
- GstEvent * event);
-static GstFlowReturn gst_gio_base_sink_render (GstBaseSink * base_sink,
- GstBuffer * buffer);
-static gboolean gst_gio_base_sink_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_gio_base_sink_base_init (gpointer gclass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_base_sink_debug, "gio_base_sink", 0,
- "GIO base sink");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
-}
-
-static void
-gst_gio_base_sink_class_init (GstGioBaseSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
-
- gobject_class->finalize = gst_gio_base_sink_finalize;
-
- gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_sink_start);
- gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_sink_stop);
- gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock);
- gstbasesink_class->unlock_stop =
- GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock_stop);
- gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_gio_base_sink_event);
- gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_gio_base_sink_render);
-}
-
-static void
-gst_gio_base_sink_init (GstGioBaseSink * sink, GstGioBaseSinkClass * gclass)
-{
- gst_pad_set_query_function (GST_BASE_SINK_PAD (sink),
- GST_DEBUG_FUNCPTR (gst_gio_base_sink_query));
-
- gst_base_sink_set_sync (GST_BASE_SINK (sink), FALSE);
-
- sink->cancel = g_cancellable_new ();
-}
-
-static void
-gst_gio_base_sink_finalize (GObject * object)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (object);
-
- if (sink->cancel) {
- g_object_unref (sink->cancel);
- sink->cancel = NULL;
- }
-
- if (sink->stream) {
- g_object_unref (sink->stream);
- sink->stream = NULL;
- }
-
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static gboolean
-gst_gio_base_sink_start (GstBaseSink * base_sink)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
- if (!G_IS_OUTPUT_STREAM (sink->stream)) {
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("No stream given yet"));
- return FALSE;
- }
-
- sink->position = 0;
-
- GST_DEBUG_OBJECT (sink, "started stream");
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_stop (GstBaseSink * base_sink)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
- gboolean success;
- GError *err = NULL;
-
- if (G_IS_OUTPUT_STREAM (sink->stream)) {
- GST_DEBUG_OBJECT (sink, "closing stream");
-
- /* FIXME: can block but unfortunately we can't use async operations
- * here because they require a running main loop */
- success = g_output_stream_close (sink->stream, sink->cancel, &err);
-
- if (!success && !gst_gio_error (sink, "g_output_stream_close", &err, NULL)) {
- GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
- ("g_ooutput_stream_close failed: %s", err->message));
- g_clear_error (&err);
- } else if (!success) {
- GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
- ("g_output_stream_close failed"));
- } else {
- GST_DEBUG_OBJECT (sink, "g_outut_stream_close succeeded");
- }
-
- g_object_unref (sink->stream);
- sink->stream = NULL;
- }
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_unlock (GstBaseSink * base_sink)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
- GST_LOG_OBJECT (sink, "triggering cancellation");
-
- g_cancellable_cancel (sink->cancel);
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
-
- GST_LOG_OBJECT (sink, "resetting cancellable");
-
- g_cancellable_reset (sink->cancel);
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_sink_event (GstBaseSink * base_sink, GstEvent * event)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
- GstFlowReturn ret = GST_FLOW_OK;
-
- if (sink->stream == NULL)
- return TRUE;
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:
- if (G_IS_OUTPUT_STREAM (sink->stream)) {
- GstFormat format;
- gint64 offset;
-
- gst_event_parse_new_segment (event, NULL, NULL, &format, &offset, NULL,
- NULL);
-
- if (format != GST_FORMAT_BYTES) {
- GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format",
- gst_format_get_name (format));
- break;
- }
-
- if (GST_GIO_STREAM_IS_SEEKABLE (sink->stream)) {
- ret = gst_gio_seek (sink, G_SEEKABLE (sink->stream), offset,
- sink->cancel);
- if (ret == GST_FLOW_OK)
- sink->position = offset;
- } else {
- ret = GST_FLOW_NOT_SUPPORTED;
- }
- }
- break;
-
- case GST_EVENT_EOS:
- case GST_EVENT_FLUSH_START:
- if (G_IS_OUTPUT_STREAM (sink->stream)) {
- gboolean success;
- GError *err = NULL;
-
- success = g_output_stream_flush (sink->stream, sink->cancel, &err);
-
- if (!success && !gst_gio_error (sink, "g_output_stream_flush", &err,
- &ret)) {
- GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
- ("flush failed: %s", err->message));
- g_clear_error (&err);
- }
- }
- break;
-
- default:
- break;
- }
-
- return (ret == GST_FLOW_OK);
-}
-
-static GstFlowReturn
-gst_gio_base_sink_render (GstBaseSink * base_sink, GstBuffer * buffer)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink);
- gssize written;
- gboolean success;
- GError *err = NULL;
-
- g_return_val_if_fail (G_IS_OUTPUT_STREAM (sink->stream), GST_FLOW_ERROR);
-
- GST_LOG_OBJECT (sink, "writing %u bytes to offset %" G_GUINT64_FORMAT,
- GST_BUFFER_SIZE (buffer), sink->position);
-
- written = g_output_stream_write (sink->stream,
- GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), sink->cancel, &err);
-
- success = (written >= 0);
-
- if (G_UNLIKELY (success && written < GST_BUFFER_SIZE (buffer))) {
- /* FIXME: Can this happen? Should we handle it gracefully? gnomevfssink
- * doesn't... */
- GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
- ("Could not write to stream: (short write, only %"
- G_GUINT64_FORMAT " bytes of %d bytes written)",
- written, GST_BUFFER_SIZE (buffer)));
- return GST_FLOW_ERROR;
- }
-
- if (success) {
- sink->position += written;
- return GST_FLOW_OK;
-
- } else {
- GstFlowReturn ret;
-
- if (!gst_gio_error (sink, "g_output_stream_write", &err, &ret)) {
- GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL),
- ("Could not write to stream: %s", err->message));
- g_clear_error (&err);
- }
-
- return ret;
- }
-}
-
-static gboolean
-gst_gio_base_sink_query (GstPad * pad, GstQuery * query)
-{
- GstGioBaseSink *sink = GST_GIO_BASE_SINK (GST_PAD_PARENT (pad));
- GstFormat format;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- gst_query_parse_position (query, &format, NULL);
- switch (format) {
- case GST_FORMAT_BYTES:
- case GST_FORMAT_DEFAULT:
- gst_query_set_position (query, GST_FORMAT_BYTES, sink->position);
- return TRUE;
- default:
- return FALSE;
- }
- case GST_QUERY_FORMATS:
- gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
- return TRUE;
- default:
- return gst_pad_query_default (pad, query);
- }
-}
-
-void
-gst_gio_base_sink_set_stream (GstGioBaseSink * sink, GOutputStream * stream)
-{
- g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
- g_return_if_fail ((GST_STATE (sink) != GST_STATE_PLAYING &&
- GST_STATE (sink) != GST_STATE_PAUSED));
-
- if (G_IS_OUTPUT_STREAM (sink->stream)) {
- gboolean success;
- GError *err = NULL;
-
- GST_DEBUG_OBJECT (sink, "closing old stream");
-
- /* FIXME: can block but unfortunately we can't use async operations
- * here because they require a running main loop */
- success = g_output_stream_close (sink->stream, sink->cancel, &err);
-
- if (!success && !gst_gio_error (sink, "g_output_stream_close", &err, NULL)) {
- GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
- ("g_output_stream_close failed: %s", err->message));
- g_clear_error (&err);
- } else if (!success) {
- GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL),
- ("g_output_stream_close failed"));
- } else {
- GST_DEBUG_OBJECT (sink, "g_output_stream_close succeeded");
- }
-
- g_object_unref (sink->stream);
- sink->stream = NULL;
- }
-
- sink->stream = stream;
-}
--- a/gst_plugins_base/ext/gio/gstgiobasesink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_BASE_SINK_H__
-#define __GST_GIO_BASE_SINK_H__
-
-#include "gstgio.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_BASE_SINK \
- (gst_gio_base_sink_get_type())
-#define GST_GIO_BASE_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SINK,GstGioBaseSink))
-#define GST_GIO_BASE_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SINK,GstGioBaseSinkClass))
-#define GST_IS_GIO_BASE_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SINK))
-#define GST_IS_GIO_BASE_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SINK))
-
-typedef struct _GstGioBaseSink GstGioBaseSink;
-typedef struct _GstGioBaseSinkClass GstGioBaseSinkClass;
-
-struct _GstGioBaseSink
-{
- GstBaseSink sink;
-
- GCancellable *cancel;
- guint64 position;
- GOutputStream *stream;
-};
-
-struct _GstGioBaseSinkClass
-{
- GstBaseSinkClass parent_class;
-};
-
-GType gst_gio_base_sink_get_type (void);
-
-void gst_gio_base_sink_set_stream (GstGioBaseSink *sink, GOutputStream *stream);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_BASE_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiobasesrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,383 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 "gstgiobasesrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug);
-#define GST_CAT_DEFAULT gst_gio_base_src_debug
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-GST_BOILERPLATE (GstGioBaseSrc, gst_gio_base_src, GstBaseSrc,
- GST_TYPE_BASE_SRC);
-
-static void gst_gio_base_src_finalize (GObject * object);
-static gboolean gst_gio_base_src_start (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_stop (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_get_size (GstBaseSrc * base_src,
- guint64 * size);
-static gboolean gst_gio_base_src_is_seekable (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_unlock (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_unlock_stop (GstBaseSrc * base_src);
-static gboolean gst_gio_base_src_check_get_range (GstBaseSrc * base_src);
-static GstFlowReturn gst_gio_base_src_create (GstBaseSrc * base_src,
- guint64 offset, guint size, GstBuffer ** buf);
-
-static void
-gst_gio_base_src_base_init (gpointer gclass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_base_src_debug, "gio_base_src", 0,
- "GIO base source");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
-}
-
-static void
-gst_gio_base_src_class_init (GstGioBaseSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesrc_class = (GstBaseSrcClass *) klass;
-
- gobject_class->finalize = gst_gio_base_src_finalize;
-
- gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_src_start);
- gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_src_stop);
- gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gio_base_src_get_size);
- gstbasesrc_class->is_seekable =
- GST_DEBUG_FUNCPTR (gst_gio_base_src_is_seekable);
- gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock);
- gstbasesrc_class->unlock_stop =
- GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock_stop);
- gstbasesrc_class->check_get_range =
- GST_DEBUG_FUNCPTR (gst_gio_base_src_check_get_range);
- gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gio_base_src_create);
-}
-
-static void
-gst_gio_base_src_init (GstGioBaseSrc * src, GstGioBaseSrcClass * gclass)
-{
- src->cancel = g_cancellable_new ();
-}
-
-static void
-gst_gio_base_src_finalize (GObject * object)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (object);
-
- if (src->cancel) {
- g_object_unref (src->cancel);
- src->cancel = NULL;
- }
-
- if (src->stream) {
- g_object_unref (src->stream);
- src->stream = NULL;
- }
-
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static gboolean
-gst_gio_base_src_start (GstBaseSrc * base_src)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
- if (!G_IS_INPUT_STREAM (src->stream)) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("No stream given yet"));
- return FALSE;
- }
-
- src->position = 0;
-
- GST_DEBUG_OBJECT (src, "started stream");
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_stop (GstBaseSrc * base_src)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
- gboolean success;
- GError *err = NULL;
-
- if (G_IS_INPUT_STREAM (src->stream)) {
- GST_DEBUG_OBJECT (src, "closing stream");
-
- /* FIXME: can block but unfortunately we can't use async operations
- * here because they require a running main loop */
- success = g_input_stream_close (src->stream, src->cancel, &err);
-
- if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed: %s", err->message));
- g_clear_error (&err);
- } else if (!success) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed"));
- } else {
- GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
- }
-
- g_object_unref (src->stream);
- src->stream = NULL;
- }
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
- if (G_IS_FILE_INPUT_STREAM (src->stream)) {
- GFileInfo *info;
- GError *err = NULL;
-
- info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream),
- G_FILE_ATTRIBUTE_STANDARD_SIZE, src->cancel, &err);
-
- if (info != NULL) {
- *size = g_file_info_get_size (info);
- g_object_unref (info);
- GST_DEBUG_OBJECT (src, "found size: %" G_GUINT64_FORMAT, *size);
- return TRUE;
- }
-
- if (!gst_gio_error (src, "g_file_input_stream_query_info", &err, NULL)) {
-
- if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
- GST_DEBUG_OBJECT (src, "size information not available");
- else
- GST_WARNING_OBJECT (src, "size information retrieval failed: %s",
- err->message);
-
- g_clear_error (&err);
- }
- } else if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) {
- goffset old;
- goffset stream_size;
- gboolean ret;
- GSeekable *seekable = G_SEEKABLE (src->stream);
- GError *err = NULL;
-
- old = g_seekable_tell (seekable);
-
- ret = g_seekable_seek (seekable, 0, G_SEEK_END, src->cancel, &err);
- if (!ret) {
- if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
- if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
- GST_DEBUG_OBJECT (src,
- "Seeking to the end of stream is not supported");
- else
- GST_WARNING_OBJECT (src, "Seeking to end of stream failed: %s",
- err->message);
- g_clear_error (&err);
- } else {
- GST_WARNING_OBJECT (src, "Seeking to end of stream failed");
- }
-
- return FALSE;
- }
-
- stream_size = g_seekable_tell (seekable);
-
- ret = g_seekable_seek (seekable, old, G_SEEK_SET, src->cancel, &err);
- if (!ret) {
- if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) {
- if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED))
- GST_ERROR_OBJECT (src, "Seeking to the old position not supported");
- else
- GST_ERROR_OBJECT (src, "Seeking to the old position failed: %s",
- err->message);
- g_clear_error (&err);
- } else {
- GST_ERROR_OBJECT (src, "Seeking to the old position faile");
- }
-
- return FALSE;
- }
-
- if (stream_size >= 0) {
- *size = stream_size;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static gboolean
-gst_gio_base_src_is_seekable (GstBaseSrc * base_src)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
- gboolean seekable;
-
- seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream);
-
- GST_DEBUG_OBJECT (src, "can seek: %d", seekable);
-
- return seekable;
-}
-
-static gboolean
-gst_gio_base_src_unlock (GstBaseSrc * base_src)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
- GST_LOG_OBJECT (src, "triggering cancellation");
-
- g_cancellable_cancel (src->cancel);
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_unlock_stop (GstBaseSrc * base_src)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
-
- GST_LOG_OBJECT (src, "resetting cancellable");
-
- g_cancellable_reset (src->cancel);
-
- return TRUE;
-}
-
-static gboolean
-gst_gio_base_src_check_get_range (GstBaseSrc * base_src)
-{
- /* FIXME: Implement dry-run variant using guesswork like gnomevfssrc? */
-
- return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS,
- check_get_range, (base_src), FALSE);
-}
-
-static GstFlowReturn
-gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size,
- GstBuffer ** buf_return)
-{
- GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src);
- GstBuffer *buf;
- gssize read;
- gboolean success, eos;
- GstFlowReturn ret = GST_FLOW_OK;
- GError *err = NULL;
-
- g_return_val_if_fail (G_IS_INPUT_STREAM (src->stream), GST_FLOW_ERROR);
-
- if (G_UNLIKELY (offset != src->position)) {
- if (!GST_GIO_STREAM_IS_SEEKABLE (src->stream))
- return GST_FLOW_NOT_SUPPORTED;
-
- ret = gst_gio_seek (src, G_SEEKABLE (src->stream), offset, src->cancel);
-
- if (ret == GST_FLOW_OK)
- src->position = offset;
- else
- return ret;
- }
-
- buf = gst_buffer_new_and_alloc (size);
-
- GST_LOG_OBJECT (src, "reading %u bytes from offset %" G_GUINT64_FORMAT,
- size, offset);
-
- read =
- g_input_stream_read (G_INPUT_STREAM (src->stream), GST_BUFFER_DATA (buf),
- size, src->cancel, &err);
-
- success = (read >= 0);
- eos = (size > 0 && read == 0);
-
- if (!success && !gst_gio_error (src, "g_input_stream_read", &err, &ret)) {
- GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
- ("Could not read from stream: %s", err->message));
- g_clear_error (&err);
- }
-
- if (success && !eos) {
- src->position += read;
- GST_BUFFER_OFFSET (buf) = offset;
- GST_BUFFER_SIZE (buf) = read;
- *buf_return = buf;
- } else {
- /* !success || eos */
- gst_buffer_unref (buf);
- }
-
- if (eos)
- ret = GST_FLOW_UNEXPECTED;
-
- return ret;
-}
-
-void
-gst_gio_base_src_set_stream (GstGioBaseSrc * src, GInputStream * stream)
-{
- gboolean success;
- GError *err = NULL;
-
- g_return_if_fail (G_IS_INPUT_STREAM (stream));
- g_return_if_fail ((GST_STATE (src) != GST_STATE_PLAYING &&
- GST_STATE (src) != GST_STATE_PAUSED));
-
- if (G_IS_INPUT_STREAM (src->stream)) {
- GST_DEBUG_OBJECT (src, "closing old stream");
-
- /* FIXME: can block but unfortunately we can't use async operations
- * here because they require a running main loop */
- success = g_input_stream_close (src->stream, src->cancel, &err);
-
- if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed: %s", err->message));
- g_clear_error (&err);
- } else if (!success) {
- GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL),
- ("g_input_stream_close failed"));
- } else {
- GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded");
- }
-
- g_object_unref (src->stream);
- src->stream = NULL;
- }
-
- src->stream = stream;
-}
--- a/gst_plugins_base/ext/gio/gstgiobasesrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_BASE_SRC_H__
-#define __GST_GIO_BASE_SRC_H__
-
-#include "gstgio.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_BASE_SRC \
- (gst_gio_base_src_get_type())
-#define GST_GIO_BASE_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc))
-#define GST_GIO_BASE_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass))
-#define GST_IS_GIO_BASE_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SRC))
-#define GST_IS_GIO_BASE_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SRC))
-
-typedef struct _GstGioBaseSrc GstGioBaseSrc;
-typedef struct _GstGioBaseSrcClass GstGioBaseSrcClass;
-
-struct _GstGioBaseSrc
-{
- GstBaseSrc src;
-
- GCancellable *cancel;
- guint64 position;
- GInputStream *stream;
-};
-
-struct _GstGioBaseSrcClass
-{
- GstBaseSrcClass parent_class;
-};
-
-GType gst_gio_base_src_get_type (void);
-
-void gst_gio_base_src_set_stream (GstGioBaseSrc *src, GInputStream *stream);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_BASE_SRC_H__ */
--- a/gst_plugins_base/ext/gio/gstgiosink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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.
- */
-
-/**
- * SECTION:element-giosink
- * @short_description: Write a stream to any GIO-supported location
- * @see_also: #GstFileSink, #GstGnomeVFSSink, #GstGioSrc
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GIO library or it's VFS backends. Common protocols are 'file', 'ftp',
- * or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=input.xyz ! giosink location=file:///home/joe/out.xyz
- * </programlisting>
- * The above pipeline will simply copy a local file. Instead of giosink,
- * we could just as well have used the filesink element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! giosink location=smb://othercomputer/foo.flac
- * </programlisting>
- * The above pipeline will re-encode an mp3 file into FLAC format and store
- * it on a remote host using the Samba protocol.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v audiotestsrc num-buffers=100 ! vorbisenc ! oggmux ! giosink location=file:///home/foo/bar.ogg
- * </programlisting>
- * The above pipeline will encode a 440Hz sine wave to Ogg Vorbis and stores
- * it in the home directory of user foo.
- * </para>
- * </refsect2>
- */
-
-/* FIXME: We would like to mount the enclosing volume of an URL
- * if it isn't mounted yet but this is possible async-only.
- * Unfortunately this requires a running main loop from the
- * default context and we can't guarantuee this!
- *
- * We would also like to do authentication while mounting.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiosink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_sink_debug
-
-/* Filter signals and args */
-enum
-{
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_LOCATION
-};
-
-GST_BOILERPLATE_FULL (GstGioSink, gst_gio_sink, GstGioBaseSink,
- GST_TYPE_GIO_BASE_SINK, gst_gio_uri_handler_do_init);
-
-static void gst_gio_sink_finalize (GObject * object);
-static void gst_gio_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gio_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_gio_sink_start (GstBaseSink * base_sink);
-
-static void
-gst_gio_sink_base_init (gpointer gclass)
-{
- static GstElementDetails element_details = {
- "GIO sink",
- "Sink/File",
- "Write to any GIO-supported location",
- "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_sink_debug, "gio_sink", 0, "GIO sink");
-
- gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_sink_class_init (GstGioSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
-
- gobject_class->finalize = gst_gio_sink_finalize;
- gobject_class->set_property = gst_gio_sink_set_property;
- gobject_class->get_property = gst_gio_sink_get_property;
-
- g_object_class_install_property (gobject_class, ARG_LOCATION,
- g_param_spec_string ("location", "Location", "URI location to write to",
- NULL, G_PARAM_READWRITE));
-
- gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_sink_start);
-}
-
-static void
-gst_gio_sink_init (GstGioSink * sink, GstGioSinkClass * gclass)
-{
-}
-
-static void
-gst_gio_sink_finalize (GObject * object)
-{
- GstGioSink *sink = GST_GIO_SINK (object);
-
- if (sink->location) {
- g_free (sink->location);
- sink->location = NULL;
- }
-
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGioSink *sink = GST_GIO_SINK (object);
-
- switch (prop_id) {
- case ARG_LOCATION:
- if (GST_STATE (sink) == GST_STATE_PLAYING ||
- GST_STATE (sink) == GST_STATE_PAUSED)
- break;
-
- g_free (sink->location);
- sink->location = g_strdup (g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gio_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstGioSink *sink = GST_GIO_SINK (object);
-
- switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, sink->location);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_gio_sink_start (GstBaseSink * base_sink)
-{
- GstGioSink *sink = GST_GIO_SINK (base_sink);
- GFile *file;
- GOutputStream *stream;
- GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel;
- gboolean success;
- GError *err = NULL;
-
- if (sink->location == NULL) {
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("No location given"));
- return FALSE;
- }
-
- file = g_file_new_for_uri (sink->location);
-
- if (file == NULL) {
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("Malformed URI or protocol not supported (%s)", sink->location));
- return FALSE;
- }
-
- stream =
- G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, cancel, &err));
-
- success = (stream != NULL);
-
- g_object_unref (file);
-
- if (!success && !gst_gio_error (sink, "g_file_create", &err, NULL)) {
-
- /*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */
- /* FIXME: Retry with replace if overwrite == TRUE! */
-
- if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND))
- GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL),
- ("Could not open location %s for writing: %s",
- sink->location, err->message));
- else
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_READ, (NULL),
- ("Could not open location %s for writing: %s",
- sink->location, err->message));
-
- g_clear_error (&err);
- }
-
- if (!success)
- return FALSE;
-
- GST_DEBUG_OBJECT (sink, "opened location %s", sink->location);
-
- gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink), stream);
-
- return GST_BASE_SINK_CLASS (parent_class)->start (base_sink);
-}
--- a/gst_plugins_base/ext/gio/gstgiosink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_SINK_H__
-#define __GST_GIO_SINK_H__
-
-#include "gstgio.h"
-#include "gstgiobasesink.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_SINK \
- (gst_gio_sink_get_type())
-#define GST_GIO_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SINK,GstGioSink))
-#define GST_GIO_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SINK,GstGioSinkClass))
-#define GST_IS_GIO_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SINK))
-#define GST_IS_GIO_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SINK))
-
-typedef struct _GstGioSink GstGioSink;
-typedef struct _GstGioSinkClass GstGioSinkClass;
-
-/**
- * GstGioSink:
- *
- * Opaque data structure.
- */
-struct _GstGioSink
-{
- GstGioBaseSink sink;
-
- /*< private >*/
- gchar *location;
-
- GMainLoop *loop;
- gboolean mount_successful;
-};
-
-struct _GstGioSinkClass
-{
- GstGioBaseSinkClass parent_class;
-};
-
-GType gst_gio_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiosrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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.
- */
-
-/**
- * SECTION:element-giosrc
- * @short_description: Read from any GIO-supported location
- * @see_also: #GstFileSrc, #GstGnomeVFSSrc, #GstGioSink
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GIO library or it's VFS backends. Common protocols are 'file', 'http',
- * 'ftp', or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=file:///home/joe/foo.xyz ! fakesink
- * </programlisting>
- * The above pipeline will simply read a local file and do nothing with the
- * data read. Instead of giosrc, we could just as well have used the
- * filesrc element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz
- * </programlisting>
- * The above pipeline will copy a file from a remote host to the local file
- * system using the Samba protocol.
- * </para>
- * <para>
- * Yet another example pipeline:
- * <programlisting>
- * gst-launch -v giosrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * The above pipeline will read and decode and play an mp3 file from a
- * web server using the http protocol.
- * </para>
- * </refsect2>
- */
-
-/* FIXME: We would like to mount the enclosing volume of an URL
- * if it isn't mounted yet but this is possible async-only.
- * Unfortunately this requires a running main loop from the
- * default context and we can't guarantuee this!
- *
- * We would also like to do authentication while mounting.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiosrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_src_debug);
-#define GST_CAT_DEFAULT gst_gio_src_debug
-
-enum
-{
- ARG_0,
- ARG_LOCATION
-};
-
-GST_BOILERPLATE_FULL (GstGioSrc, gst_gio_src, GstGioBaseSrc,
- GST_TYPE_GIO_BASE_SRC, gst_gio_uri_handler_do_init);
-
-static void gst_gio_src_finalize (GObject * object);
-static void gst_gio_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gio_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static gboolean gst_gio_src_start (GstBaseSrc * base_src);
-
-static void
-gst_gio_src_base_init (gpointer gclass)
-{
- static GstElementDetails element_details = {
- "GIO source",
- "Source/File",
- "Read from any GIO-supported location",
- "Ren\xc3\xa9 Stadler <mail@renestadler.de>, "
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_src_debug, "gio_src", 0, "GIO source");
-
- gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_src_class_init (GstGioSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesrc_class = (GstBaseSrcClass *) klass;
-
- gobject_class->finalize = gst_gio_src_finalize;
- gobject_class->set_property = gst_gio_src_set_property;
- gobject_class->get_property = gst_gio_src_get_property;
-
- g_object_class_install_property (gobject_class, ARG_LOCATION,
- g_param_spec_string ("location", "Location", "URI location to read from",
- NULL, G_PARAM_READWRITE));
-
- gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_src_start);
-}
-
-static void
-gst_gio_src_init (GstGioSrc * src, GstGioSrcClass * gclass)
-{
-}
-
-static void
-gst_gio_src_finalize (GObject * object)
-{
- GstGioSrc *src = GST_GIO_SRC (object);
-
- if (src->location) {
- g_free (src->location);
- src->location = NULL;
- }
-
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGioSrc *src = GST_GIO_SRC (object);
-
- switch (prop_id) {
- case ARG_LOCATION:
- if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
- break;
-
- g_free (src->location);
- src->location = g_strdup (g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gio_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstGioSrc *src = GST_GIO_SRC (object);
-
- switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, src->location);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_gio_src_start (GstBaseSrc * base_src)
-{
- GstGioSrc *src = GST_GIO_SRC (base_src);
- GFile *file;
- GError *err = NULL;
- GInputStream *stream;
- GCancellable *cancel = GST_GIO_BASE_SRC (src)->cancel;
-
- if (src->location == NULL) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No location given"));
- return FALSE;
- }
-
- file = g_file_new_for_uri (src->location);
-
- if (file == NULL) {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Malformed URI or protocol not supported (%s)", src->location));
- return FALSE;
- }
-
- stream = G_INPUT_STREAM (g_file_read (file, cancel, &err));
-
- g_object_unref (file);
-
- if (stream == NULL && !gst_gio_error (src, "g_file_read", &err, NULL)) {
-
- if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) {
- GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
- ("Could not open location %s for reading: %s",
- src->location, err->message));
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Could not open location %s for reading: %s",
- src->location, err->message));
- }
-
- g_clear_error (&err);
- return FALSE;
- } else if (stream == NULL) {
- return FALSE;
- }
-
- gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src), stream);
-
- GST_DEBUG_OBJECT (src, "opened location %s", src->location);
-
- return GST_BASE_SRC_CLASS (parent_class)->start (base_src);
-}
--- a/gst_plugins_base/ext/gio/gstgiosrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_SRC_H__
-#define __GST_GIO_SRC_H__
-
-#include "gstgio.h"
-#include "gstgiobasesrc.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_SRC \
- (gst_gio_src_get_type())
-#define GST_GIO_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SRC,GstGioSrc))
-#define GST_GIO_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SRC,GstGioSrcClass))
-#define GST_IS_GIO_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SRC))
-#define GST_IS_GIO_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SRC))
-
-typedef struct _GstGioSrc GstGioSrc;
-typedef struct _GstGioSrcClass GstGioSrcClass;
-
-/**
- * GstGioSrc:
- *
- * Opaque data structure.
- */
-struct _GstGioSrc
-{
- GstGioBaseSrc src;
-
- /*< private >*/
- gchar *location;
-
- GMainLoop *loop;
- gboolean mount_successful;
-};
-
-struct _GstGioSrcClass
-{
- GstGioBaseSrcClass parent_class;
-};
-
-GType gst_gio_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_SRC_H__ */
--- a/gst_plugins_base/ext/gio/gstgiostreamsink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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.
- */
-
-/**
- * SECTION:element-giostreamsink
- * @short_description: Write to a GIO GOutputStream
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a custom GIO #GOutputStream.
- * </para>
- * <para>
- * It can, for example, be used to write a stream to memory with a
- * #GMemoryOuputStream or to write to a file with a #GFileOuputStream.
- * </para>
- * <title>Example code</title>
- * <para>
- * The following example writes the received data to a #GMemoryOutputStream.
- * <programlisting>
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-
-...
-
-GstElement *sink;
-GMemoryOuputStream *stream;
-// out_data will contain the received data
-guint8 *out_data;
-
-...
-
-stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0,
- (GReallocFunc) g_realloc, (GDestroyNotify) g_free));
-sink = gst_element_factory_make ("giostreamsink", "sink");
-g_object_set (G_OBJECT (sink), "stream", stream, NULL);
-
-...
-
-// after processing get the written data
-out_data = g_memory_ouput_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream));
-
-...
-
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiostreamsink.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_sink_debug);
-#define GST_CAT_DEFAULT gst_gio_stream_sink_debug
-
-/* Filter signals and args */
-enum
-{
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_STREAM
-};
-
-GST_BOILERPLATE (GstGioStreamSink, gst_gio_stream_sink, GstGioBaseSink,
- GST_TYPE_GIO_BASE_SINK);
-
-static void gst_gio_stream_sink_finalize (GObject * object);
-static void gst_gio_stream_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gio_stream_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static void
-gst_gio_stream_sink_base_init (gpointer gclass)
-{
- static GstElementDetails element_details = {
- "GIO stream sink",
- "Sink",
- "Write to any GIO stream",
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_stream_sink_debug, "gio_stream_sink", 0,
- "GIO stream sink");
-
- gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_stream_sink_class_init (GstGioStreamSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
-
- gobject_class->finalize = gst_gio_stream_sink_finalize;
- gobject_class->set_property = gst_gio_stream_sink_set_property;
- gobject_class->get_property = gst_gio_stream_sink_get_property;
-
- g_object_class_install_property (gobject_class, ARG_STREAM,
- g_param_spec_object ("stream", "Stream", "Stream to write to",
- G_TYPE_OUTPUT_STREAM, G_PARAM_READWRITE));
-}
-
-static void
-gst_gio_stream_sink_init (GstGioStreamSink * sink,
- GstGioStreamSinkClass * gclass)
-{
-}
-
-static void
-gst_gio_stream_sink_finalize (GObject * object)
-{
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_stream_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object);
-
- switch (prop_id) {
- case ARG_STREAM:{
- GObject *stream;
-
- if (GST_STATE (sink) == GST_STATE_PLAYING ||
- GST_STATE (sink) == GST_STATE_PAUSED)
- break;
-
- stream = g_value_dup_object (value);
- if (G_IS_OUTPUT_STREAM (stream))
- gst_gio_base_sink_set_stream (GST_GIO_BASE_SINK (sink),
- G_OUTPUT_STREAM (stream));
-
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gio_stream_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object);
-
- switch (prop_id) {
- case ARG_STREAM:
- g_value_set_object (value, GST_GIO_BASE_SINK (sink)->stream);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
--- a/gst_plugins_base/ext/gio/gstgiostreamsink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_STREAM_SINK_H__
-#define __GST_GIO_STREAM_SINK_H__
-
-#include "gstgio.h"
-#include "gstgiobasesink.h"
-
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_STREAM_SINK \
- (gst_gio_stream_sink_get_type())
-#define GST_GIO_STREAM_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSink))
-#define GST_GIO_STREAM_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSinkClass))
-#define GST_IS_GIO_STREAM_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SINK))
-#define GST_IS_GIO_STREAM_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SINK))
-
-typedef struct _GstGioStreamSink GstGioStreamSink;
-typedef struct _GstGioStreamSinkClass GstGioStreamSinkClass;
-
-/**
- * GstGioStreamSink:
- *
- * Opaque data structure.
- */
-struct _GstGioStreamSink
-{
- GstGioBaseSink sink;
-};
-
-struct _GstGioStreamSinkClass
-{
- GstGioBaseSinkClass parent_class;
-};
-
-GType gst_gio_stream_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_STREAM_SINK_H__ */
--- a/gst_plugins_base/ext/gio/gstgiostreamsrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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.
- */
-
-/**
- * SECTION:element-giostreamsrc
- * @short_description: Reads data from a GIO GInputStream
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a custom GIO #GInputStream.
- * </para>
- * <para>
- * It can, for example, be used to read data from memory with a
- * #GMemoryInputStream or to read from a file with a
- * #GFileInputStream.
- * </para>
- * <title>Example code</title>
- * <para>
- * The following example reads data from a #GMemoryOutputStream.
- * <programlisting>
-
-#include <gst/gst.h>
-#include <gio/gio.h>
-
-...
-
-GstElement *src;
-GMemoryInputStream *stream;
-// in_data will contain the data to send
-guint8 *in_data;
-gint i;
-
-...
-in_data = g_new (guint8, 512);
-for (i = 0; i < 512; i++)
- in_data[i] = i % 256;
-
-stream = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (in_data, 512,
- (GDestroyNotify) g_free));
-src = gst_element_factory_make ("giostreamsrc", "src");
-g_object_set (G_OBJECT (src), "stream", stream, NULL);
-
-...
-
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstgiostreamsrc.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_src_debug);
-#define GST_CAT_DEFAULT gst_gio_stream_src_debug
-
-enum
-{
- ARG_0,
- ARG_STREAM
-};
-
-GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc,
- GST_TYPE_GIO_BASE_SRC);
-
-static void gst_gio_stream_src_finalize (GObject * object);
-static void gst_gio_stream_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gio_stream_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static void
-gst_gio_stream_src_base_init (gpointer gclass)
-{
- static GstElementDetails element_details = {
- "GIO stream source",
- "Source",
- "Read from any GIO stream",
- "Sebastian Dröge <slomo@circular-chaos.org>"
- };
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- GST_DEBUG_CATEGORY_INIT (gst_gio_stream_src_debug, "gio_stream_src", 0,
- "GIO source");
-
- gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesrc_class = (GstBaseSrcClass *) klass;
-
- gobject_class->finalize = gst_gio_stream_src_finalize;
- gobject_class->set_property = gst_gio_stream_src_set_property;
- gobject_class->get_property = gst_gio_stream_src_get_property;
-
- g_object_class_install_property (gobject_class, ARG_STREAM,
- g_param_spec_object ("stream", "Stream", "Stream to read from",
- G_TYPE_INPUT_STREAM, G_PARAM_READWRITE));
-}
-
-static void
-gst_gio_stream_src_init (GstGioStreamSrc * src, GstGioStreamSrcClass * gclass)
-{
-}
-
-static void
-gst_gio_stream_src_finalize (GObject * object)
-{
- GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
-}
-
-static void
-gst_gio_stream_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
-
- switch (prop_id) {
- case ARG_STREAM:{
- GObject *stream;
-
- if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
- break;
-
- stream = g_value_dup_object (value);
- if (G_IS_INPUT_STREAM (stream))
- gst_gio_base_src_set_stream (GST_GIO_BASE_SRC (src),
- G_INPUT_STREAM (stream));
-
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gio_stream_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object);
-
- switch (prop_id) {
- case ARG_STREAM:
- g_value_set_object (value, GST_GIO_BASE_SRC (src)->stream);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
--- a/gst_plugins_base/ext/gio/gstgiostreamsrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2007 Rene Stadler <mail@renestadler.de>
- * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
- *
- * 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 __GST_GIO_STREAM_SRC_H__
-#define __GST_GIO_STREAM_SRC_H__
-
-#include "gstgio.h"
-#include "gstgiobasesrc.h"
-
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GIO_STREAM_SRC \
- (gst_gio_stream_src_get_type())
-#define GST_GIO_STREAM_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrc))
-#define GST_GIO_STREAM_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrcClass))
-#define GST_IS_GIO_STREAM_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SRC))
-#define GST_IS_GIO_STREAM_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SRC))
-
-typedef struct _GstGioStreamSrc GstGioStreamSrc;
-typedef struct _GstGioStreamSrcClass GstGioStreamSrcClass;
-
-/**
- * GstGioStreamSrc:
- *
- * Opaque data structure.
- */
-struct _GstGioStreamSrc
-{
- GstGioBaseSrc src;
-};
-
-struct _GstGioStreamSrcClass
-{
- GstGioBaseSrcClass parent_class;
-};
-
-GType gst_gio_stream_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GIO_STREAM_SRC_H__ */
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfs.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * gnomevfs.c: register gnomevfs elements
- *
- * 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 "gst/gst-i18n-plugin.h"
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfssrc.h"
-#include "gstgnomevfssink.h"
-
-#include <libgnomevfs/gnome-vfs.h>
-#include <gst/gst.h>
-
-#include <string.h>
-
-gchar *
-gst_gnome_vfs_location_to_uri_string (const gchar * location)
-{
- gchar *newloc, *ret;
-
- if (location == NULL)
- return NULL;
-
- /* already an URI string? */
- if (strstr (location, "://"))
- return g_strdup (location);
-
- newloc = gnome_vfs_escape_path_string (location);
-
- if (newloc && *newloc == '/') {
- ret = g_strdup_printf ("file://%s", newloc);
- } else {
- gchar *curdir;
-
- curdir = g_get_current_dir ();
- ret = g_strdup_printf ("file://%s/%s", curdir, newloc);
- g_free (curdir);
- }
-
- g_free (newloc);
- return ret;
-}
-
-GType
-gst_gnome_vfs_uri_get_type (void)
-{
- static GType type; /* 0 */
-
- if (type == 0) {
- type = g_boxed_type_register_static ("GnomeVFSURI",
- (GBoxedCopyFunc) gnome_vfs_uri_ref,
- (GBoxedFreeFunc) gnome_vfs_uri_unref);
- }
-
- return type;
-}
-
-static gpointer
-gst_gnome_vfs_handle_copy (gpointer handle)
-{
- return handle;
-}
-
-static void
-gst_gnome_vfs_handle_free (gpointer handle)
-{
- return;
-}
-
-GType
-gst_gnome_vfs_handle_get_type (void)
-{
- static GType type; /* 0 */
-
- if (type == 0) {
- /* hackish, but makes it show up nicely in gst-inspect */
- type = g_boxed_type_register_static ("GnomeVFSHandle",
- (GBoxedCopyFunc) gst_gnome_vfs_handle_copy,
- (GBoxedFreeFunc) gst_gnome_vfs_handle_free);
- }
-
- return type;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- /* gnome vfs engine init */
- if (!gnome_vfs_initialized ()) {
- if (!gnome_vfs_init ()) {
- GST_WARNING ("Failed to initialize GnomeVFS - not registering plugin!");
- return FALSE;
- }
- }
-
- if (!gst_element_register (plugin, "gnomevfssrc", GST_RANK_SECONDARY,
- gst_gnome_vfs_src_get_type ()))
- return FALSE;
-
- if (!gst_element_register (plugin, "gnomevfssink", GST_RANK_SECONDARY,
- gst_gnome_vfs_sink_get_type ()))
- return FALSE;
-
-#ifdef ENABLE_NLS
-/* FIXME: add category
- GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, LOCALEDIR);
- */
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif /* ENABLE_NLS */
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "gnomevfs",
- "elements to read from and write to Gnome-VFS uri's",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfs.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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 __GST_GNOME_VFS_H__
-#define __GST_GNOME_VFS_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_URI (gst_gnome_vfs_uri_get_type ())
-#define GST_TYPE_GNOME_VFS_HANDLE (gst_gnome_vfs_handle_get_type ())
-
-GType gst_gnome_vfs_uri_get_type (void);
-GType gst_gnome_vfs_handle_get_type (void);
-
-gchar * gst_gnome_vfs_location_to_uri_string (const gchar * location);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_H__ */
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,641 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2001 Bastien Nocera <hadess@hadess.net>
- * 2003 Colin Walters <walters@verbum.org>
- * 2005 Tim-Philipp Müller <tim centricular net>
- *
- * gstgnomevfssink.c:
- *
- * 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.
- */
-
-/**
- * SECTION:element-gnomevfssink
- * @short_description: Write a stream to a GnomeVFS URI
- * @see_also: #GstFileSink, #GstGnomeVFSSrc
- *
- * <refsect2>
- * <para>
- * This plugin writes incoming data to a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GnomeVFS library. Common protocols are 'file', 'ftp', or 'smb'.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=input.xyz ! gnomevfssink location=file:///home/joe/out.xyz
- * </programlisting>
- * The above pipeline will simply copy a local file. Instead of gnomevfssink,
- * we could just as well have used the filesink element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! gnomevfssink location=smb://othercomputer/foo.flac
- * </programlisting>
- * The above pipeline will re-encode an mp3 file into FLAC format and store
- * it on a remote host using the Samba protocol.
- * </para>
- * <para>
- * Applications can connect to the allow-overwrite signal to receive a callback when an
- * existing file will be overwritten. The return value of the signal will determine if
- * gnomevfssink will overwrite the resource or abort with an error.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-02-28 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstgnomevfssink.h"
-
-#include "gst/gst-i18n-plugin.h"
-
-#include <gst/gst.h>
-#include <libgnomevfs/gnome-vfs.h>
-#include <string.h>
-#include <errno.h>
-
-static const GstElementDetails gst_gnome_vfs_sink_details =
-GST_ELEMENT_DETAILS ("GnomeVFS Sink",
- "Sink/File",
- "Write a stream to a GnomeVFS URI",
- "Bastien Nocera <hadess@hadess.net>");
-
-enum
-{
- SIGNAL_ERASE_ASK,
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_LOCATION,
- ARG_URI,
- ARG_HANDLE
-};
-
-static void gst_gnome_vfs_sink_finalize (GObject * obj);
-
-static void gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface,
- gpointer iface_data);
-
-static void gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink);
-static void gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink);
-static gboolean gst_gnome_vfs_sink_start (GstBaseSink * basesink);
-static gboolean gst_gnome_vfs_sink_stop (GstBaseSink * basesink);
-static GstFlowReturn gst_gnome_vfs_sink_render (GstBaseSink * basesink,
- GstBuffer * buffer);
-static gboolean gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink,
- GstEvent * event);
-static gboolean gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query);
-
-static guint gst_gnome_vfs_sink_signals[LAST_SIGNAL]; /* all 0 */
-
-static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-GST_DEBUG_CATEGORY_STATIC (gst_gnome_vfs_sink_debug);
-#define GST_CAT_DEFAULT gst_gnome_vfs_sink_debug
-
-static void
-gst_gnome_vfs_sink_do_init (GType type)
-{
- static const GInterfaceInfo urihandler_info = {
- gst_gnome_vfs_sink_uri_handler_init,
- NULL,
- NULL
- };
-
- g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
-
- GST_DEBUG_CATEGORY_INIT (gst_gnome_vfs_sink_debug, "gnomevfssink", 0,
- "Gnome VFS sink element");
-}
-
-GST_BOILERPLATE_FULL (GstGnomeVFSSink, gst_gnome_vfs_sink, GstBaseSink,
- GST_TYPE_BASE_SINK, gst_gnome_vfs_sink_do_init);
-
-static void
-gst_gnome_vfs_sink_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sinktemplate));
-
- gst_element_class_set_details (element_class, &gst_gnome_vfs_sink_details);
-}
-
-static gboolean
-_gst_boolean_allow_overwrite_accumulator (GSignalInvocationHint * ihint,
- GValue * return_accu, const GValue * handler_return, gpointer dummy)
-{
- gboolean allow_overwrite;
-
- allow_overwrite = g_value_get_boolean (handler_return);
- if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
- g_value_set_boolean (return_accu, allow_overwrite);
-
- /* stop emission if signal doesn't allow overwriting */
- return allow_overwrite;
-}
-
-static void
-gst_gnome_vfs_sink_class_init (GstGnomeVFSSinkClass * klass)
-{
- GstBaseSinkClass *basesink_class;
- GObjectClass *gobject_class;
-
- gobject_class = (GObjectClass *) klass;
- basesink_class = (GstBaseSinkClass *) klass;
-
- gobject_class->set_property = gst_gnome_vfs_sink_set_property;
- gobject_class->get_property = gst_gnome_vfs_sink_get_property;
- gobject_class->finalize = gst_gnome_vfs_sink_finalize;
-
- g_object_class_install_property (gobject_class, ARG_LOCATION,
- g_param_spec_string ("location", "File Location",
- "Location of the file to write", NULL, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_URI,
- g_param_spec_boxed ("uri", "GnomeVFSURI", "URI for GnomeVFS",
- GST_TYPE_GNOME_VFS_URI, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_HANDLE,
- g_param_spec_boxed ("handle",
- "GnomeVFSHandle", "Handle for GnomeVFS",
- GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE));
-
- /**
- * GstGnomeVFSSink::allow-overwrite
- * @sink: the object which received the signal
- * @uri: the URI to be overwritten
- *
- * This signal is fired when gnomevfssink is about to overwrite an
- * existing resource. The application can connect to this signal and ask
- * the user if the resource may be overwritten.
- *
- * Returns: A boolean indicating that the resource may be overwritten.
- */
- gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK] =
- g_signal_new ("allow-overwrite", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET (GstGnomeVFSSinkClass, erase_ask),
- _gst_boolean_allow_overwrite_accumulator, NULL,
- gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_GNOME_VFS_URI);
-
- basesink_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_stop);
- basesink_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_start);
- basesink_class->event = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_handle_event);
- basesink_class->render = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_render);
- basesink_class->get_times = NULL;
-}
-
-static void
-gst_gnome_vfs_sink_finalize (GObject * obj)
-{
- GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (obj);
-
- if (sink->uri) {
- gnome_vfs_uri_unref (sink->uri);
- sink->uri = NULL;
- }
-
- if (sink->uri_name) {
- g_free (sink->uri_name);
- sink->uri_name = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (obj);
-}
-
-static void
-gst_gnome_vfs_sink_init (GstGnomeVFSSink * sink, GstGnomeVFSSinkClass * klass)
-{
- gst_pad_set_query_function (GST_BASE_SINK_PAD (sink),
- GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_query));
-
- sink->uri = NULL;
- sink->uri_name = NULL;
- sink->handle = NULL;
- sink->own_handle = FALSE;
- sink->current_pos = 0;
-
- GST_BASE_SINK (sink)->sync = FALSE;
-}
-
-static void
-gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGnomeVFSSink *sink;
- GstState cur_state;
-
- sink = GST_GNOME_VFS_SINK (object);
-
- gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
-
- if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) {
- GST_WARNING_OBJECT (sink, "cannot set property when PAUSED or PLAYING");
- return;
- }
-
- GST_OBJECT_LOCK (sink);
-
- switch (prop_id) {
- case ARG_LOCATION:{
- const gchar *new_location;
-
- if (sink->uri) {
- gnome_vfs_uri_unref (sink->uri);
- sink->uri = NULL;
- }
- if (sink->uri_name) {
- g_free (sink->uri_name);
- sink->uri_name = NULL;
- }
-
- new_location = g_value_get_string (value);
- if (new_location) {
- sink->uri_name = gst_gnome_vfs_location_to_uri_string (new_location);
- sink->uri = gnome_vfs_uri_new (sink->uri_name);
- }
- break;
- }
- case ARG_URI:{
- if (sink->uri) {
- gnome_vfs_uri_unref (sink->uri);
- sink->uri = NULL;
- }
- if (sink->uri_name) {
- g_free (sink->uri_name);
- sink->uri_name = NULL;
- }
- if (g_value_get_boxed (value)) {
- sink->uri = (GnomeVFSURI *) g_value_dup_boxed (value);
- sink->uri_name = gnome_vfs_uri_to_string (sink->uri, 0);
- }
- break;
- }
- case ARG_HANDLE:{
- if (sink->uri) {
- gnome_vfs_uri_unref (sink->uri);
- sink->uri = NULL;
- }
- if (sink->uri_name) {
- g_free (sink->uri_name);
- sink->uri_name = NULL;
- }
- sink->handle = g_value_get_boxed (value);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- GST_OBJECT_UNLOCK (sink);
-}
-
-static void
-gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstGnomeVFSSink *sink;
-
- sink = GST_GNOME_VFS_SINK (object);
-
- GST_OBJECT_LOCK (sink);
-
- switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, sink->uri_name);
- break;
- case ARG_URI:
- g_value_set_boxed (value, sink->uri);
- break;
- case ARG_HANDLE:
- g_value_set_boxed (value, sink->handle);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- GST_OBJECT_UNLOCK (sink);
-}
-
-static gboolean
-gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink)
-{
- GnomeVFSResult result;
-
- if (sink->uri) {
- /* open the file, all permissions, umask will apply */
- result = gnome_vfs_create_uri (&(sink->handle), sink->uri,
- GNOME_VFS_OPEN_WRITE, TRUE,
- GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE |
- GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE |
- GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE);
-
- /* if the file existed and the property says to ask, then ask! */
- if (result == GNOME_VFS_ERROR_FILE_EXISTS) {
- gboolean erase_anyway = FALSE;
-
- g_signal_emit (G_OBJECT (sink),
- gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK], 0, sink->uri,
- &erase_anyway);
- if (erase_anyway) {
- result = gnome_vfs_create_uri (&(sink->handle), sink->uri,
- GNOME_VFS_OPEN_WRITE, FALSE,
- GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE |
- GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE |
- GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE);
- }
- }
-
- GST_DEBUG_OBJECT (sink, "open: %s", gnome_vfs_result_to_string (result));
-
- if (result != GNOME_VFS_OK) {
- gchar *filename = gnome_vfs_uri_to_string (sink->uri,
- GNOME_VFS_URI_HIDE_PASSWORD);
-
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE,
- (_("Could not open vfs file \"%s\" for writing: %s."),
- filename, gnome_vfs_result_to_string (result)), GST_ERROR_SYSTEM);
- g_free (filename);
- return FALSE;
- }
- sink->own_handle = TRUE;
- } else if (!sink->handle) {
- GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (_("No filename given")),
- (NULL));
- return FALSE;
- } else {
- sink->own_handle = FALSE;
- }
-
- sink->current_pos = 0;
-
- return TRUE;
-}
-
-static void
-gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink)
-{
- GnomeVFSResult result;
-
- if (sink->own_handle) {
- /* close the file */
- result = gnome_vfs_close (sink->handle);
-
- if (result != GNOME_VFS_OK) {
- gchar *filename = gnome_vfs_uri_to_string (sink->uri,
- GNOME_VFS_URI_HIDE_PASSWORD);
-
- GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE,
- (_("Could not close vfs file \"%s\"."), filename), GST_ERROR_SYSTEM);
- g_free (filename);
- }
-
- sink->own_handle = FALSE;
- sink->handle = NULL;
- }
-}
-
-static gboolean
-gst_gnome_vfs_sink_start (GstBaseSink * basesink)
-{
- gboolean ret;
-
- ret = gst_gnome_vfs_sink_open_file (GST_GNOME_VFS_SINK (basesink));
-
- return ret;
-}
-
-static gboolean
-gst_gnome_vfs_sink_stop (GstBaseSink * basesink)
-{
- GST_DEBUG_OBJECT (basesink, "closing ...");
- gst_gnome_vfs_sink_close_file (GST_GNOME_VFS_SINK (basesink));
- return TRUE;
-}
-
-static gboolean
-gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
-{
- GstGnomeVFSSink *sink;
- gboolean ret = TRUE;
-
- sink = GST_GNOME_VFS_SINK (basesink);
-
- GST_DEBUG_OBJECT (sink, "processing %s event", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:{
- GnomeVFSResult res;
- GstFormat format;
- gint64 offset;
-
- gst_event_parse_new_segment (event, NULL, NULL, &format, &offset,
- NULL, NULL);
-
- if (format != GST_FORMAT_BYTES) {
- GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format",
- gst_format_get_name (format));
- break;
- }
-
- GST_LOG_OBJECT (sink, "seeking to offset %" G_GINT64_FORMAT, offset);
- res = gnome_vfs_seek (sink->handle, GNOME_VFS_SEEK_START, offset);
-
- if (res != GNOME_VFS_OK) {
- GST_ERROR_OBJECT (sink, "Failed to seek to offset %"
- G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res));
- ret = FALSE;
- } else {
- sink->current_pos = offset;
- }
-
- break;
- }
-
- case GST_EVENT_FLUSH_START:
- case GST_EVENT_EOS:{
- /* No need to flush with GnomeVfs */
- break;
- }
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query)
-{
- GstGnomeVFSSink *sink;
- GstFormat format;
-
- sink = GST_GNOME_VFS_SINK (GST_PAD_PARENT (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- gst_query_parse_position (query, &format, NULL);
- switch (format) {
- case GST_FORMAT_DEFAULT:
- case GST_FORMAT_BYTES:
- gst_query_set_position (query, GST_FORMAT_BYTES, sink->current_pos);
- return TRUE;
- default:
- return FALSE;
- }
-
- case GST_QUERY_FORMATS:
- gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
- return TRUE;
-
- default:
- return gst_pad_query_default (pad, query);
- }
-}
-
-static GstFlowReturn
-gst_gnome_vfs_sink_render (GstBaseSink * basesink, GstBuffer * buf)
-{
- GnomeVFSFileSize written, cur_pos;
- GstGnomeVFSSink *sink;
- GnomeVFSResult result;
- GstFlowReturn ret;
-
- sink = GST_GNOME_VFS_SINK (basesink);
-
- if (gnome_vfs_tell (sink->handle, &cur_pos) == GNOME_VFS_OK) {
- /* bring up to date with current position for proper reporting */
- sink->current_pos = cur_pos;
- }
-
- result = gnome_vfs_write (sink->handle, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf), &written);
-
- switch (result) {
- case GNOME_VFS_OK:{
- GST_DEBUG_OBJECT (sink, "wrote %" G_GINT64_FORMAT " bytes at %"
- G_GINT64_FORMAT, (gint64) written, (gint64) cur_pos);
-
- if (written < GST_BUFFER_SIZE (buf)) {
- /* FIXME: what to do here? (tpm) */
- g_warning ("%s: %d bytes should be written, only %"
- G_GUINT64_FORMAT " bytes written", G_STRLOC,
- GST_BUFFER_SIZE (buf), written);
- }
-
- sink->current_pos += GST_BUFFER_SIZE (buf);
- ret = GST_FLOW_OK;
- break;
- }
- case GNOME_VFS_ERROR_NO_SPACE:{
- /* TODO: emit signal/send msg on out-of-diskspace and
- * handle this gracefully (see open bug) (tpm) */
- GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL),
- ("bufsize=%u, written=%u", GST_BUFFER_SIZE (buf), (guint) written));
- ret = GST_FLOW_ERROR;
- break;
- }
- default:{
- gchar *filename = gnome_vfs_uri_to_string (sink->uri,
- GNOME_VFS_URI_HIDE_PASSWORD);
-
- GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
- (_("Error while writing to file \"%s\"."), filename),
- ("%s, bufsize=%u, written=%u", gnome_vfs_result_to_string (result),
- GST_BUFFER_SIZE (buf), (guint) written));
-
- g_free (filename);
- ret = GST_FLOW_ERROR;
- break;
- }
- }
-
- return GST_FLOW_OK;
-}
-
-/*** GSTURIHANDLER INTERFACE *************************************************/
-
-static GstURIType
-gst_gnome_vfs_sink_uri_get_type (void)
-{
- return GST_URI_SINK;
-}
-
-static gchar **
-gst_gnome_vfs_sink_uri_get_protocols (void)
-{
- static gchar **protocols = NULL;
-
- if (!protocols)
- protocols = gst_gnomevfs_get_supported_uris ();
-
- return protocols;
-}
-
-static const gchar *
-gst_gnome_vfs_sink_uri_get_uri (GstURIHandler * handler)
-{
- GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler);
-
- return sink->uri_name;
-}
-
-static gboolean
-gst_gnome_vfs_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri)
-{
- GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler);
- GstState cur_state;
-
- gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
-
- if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) {
- GST_WARNING_OBJECT (sink, "cannot set uri when PAUSED or PLAYING");
- return FALSE;
- }
-
- g_object_set (sink, "location", uri, NULL);
-
- return TRUE;
-}
-
-static void
-gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
- GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-
- iface->get_type = gst_gnome_vfs_sink_uri_get_type;
- iface->get_protocols = gst_gnome_vfs_sink_uri_get_protocols;
- iface->get_uri = gst_gnome_vfs_sink_uri_get_uri;
- iface->set_uri = gst_gnome_vfs_sink_uri_set_uri;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2001 Bastien Nocera <hadess@hadess.net>
- * 2003 Colin Walters <walters@verbum.org>
- * 2005 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_GNOME_VFS_SINK_H__
-#define __GST_GNOME_VFS_SINK_H__
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfsuri.h"
-#include <gst/base/gstbasesink.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_SINK \
- (gst_gnome_vfs_sink_get_type())
-#define GST_GNOME_VFS_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSink))
-#define GST_GNOME_VFS_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSinkClass))
-#define GST_IS_GNOME_VFS_SINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SINK))
-#define GST_IS_GNOME_VFS_SINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SINK))
-
-typedef struct _GstGnomeVFSSink GstGnomeVFSSink;
-typedef struct _GstGnomeVFSSinkClass GstGnomeVFSSinkClass;
-
-/**
- * GstGnomeVFSSink:
- *
- * Opaque data structure.
- */
-struct _GstGnomeVFSSink
-{
- GstBaseSink basesink;
-
- /*< private >*/
-
- /* uri */
- GnomeVFSURI *uri;
- gchar *uri_name;
-
- /* handle */
- GnomeVFSHandle *handle;
-
- /* whether we opened the handle ourselves */
- gboolean own_handle;
-
- guint64 current_pos;
-};
-
-struct _GstGnomeVFSSinkClass
-{
- GstBaseSinkClass basesink_class;
-
- /* signals */
- gboolean (*erase_ask) (GstElement * element, GnomeVFSURI * uri);
-};
-
-GType gst_gnome_vfs_sink_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_SINK_H__ */
-
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,880 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2001 Bastien Nocera <hadess@hadess.net>
- * 2002 Kristian Rietveld <kris@gtk.org>
- * 2002,2003 Colin Walters <walters@gnu.org>
- *
- * gnomevfssrc.c:
- *
- * 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.
- */
-
-/**
- * SECTION:element-gnomevfssrc
- * @short_description: Read from any GnomeVFS-supported location
- * @see_also: #GstFileSrc, #GstGnomeVFSSink
- *
- * <refsect2>
- * <para>
- * This plugin reads data from a local or remote location specified
- * by an URI. This location can be specified using any protocol supported by
- * the GnomeVFS library. Common protocols are 'file', 'http', 'ftp', or 'smb'.
- * </para>
- * <para>
- * In case the element-gnomevfssrc::iradio-mode property is set and the
- * location is a http resource, gnomevfssrc will send special icecast http
- * headers to the server to request additional icecast metainformation. If
- * the server is not an icecast server, it will display the same behaviour
- * as if the element-gnomevfssrc::iradio-mode property was not set. However,
- * if the server is in fact an icecast server, gnomevfssrc will output
- * data with a media type of application/x-icy, in which case you will
- * need to use the #ICYDemux element as follow-up element to extract
- * the icecast meta data and to determine the underlying media type.
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=file:///home/joe/foo.xyz ! fakesink
- * </programlisting>
- * The above pipeline will simply read a local file and do nothing with the
- * data read. Instead of gnomevfssrc, we could just as well have used the
- * filesrc element here.
- * </para>
- * <para>
- * Another example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz
- * </programlisting>
- * The above pipeline will copy a file from a remote host to the local file
- * system using the Samba protocol.
- * </para>
- * <para>
- * Yet another example pipeline:
- * <programlisting>
- * gst-launch -v gnomevfssrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink
- * </programlisting>
- * The above pipeline will read and decode and play an mp3 file from a
- * web server using the http protocol.
- * </para>
- * </refsect2>
- *
- */
-
-
-#define BROKEN_SIG 1
-/*#undef BROKEN_SIG */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst/gst-i18n-plugin.h"
-
-#include "gstgnomevfssrc.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <string.h>
-
-#include <gst/gst.h>
-#include <gst/tag/tag.h>
-
-/* gnome-vfs.h doesn't include the following header, which we need: */
-#include <libgnomevfs/gnome-vfs-standard-callbacks.h>
-
-GST_DEBUG_CATEGORY_STATIC (gnomevfssrc_debug);
-#define GST_CAT_DEFAULT gnomevfssrc_debug
-
-static const GstElementDetails gst_gnome_vfs_src_details =
-GST_ELEMENT_DETAILS ("GnomeVFS Source",
- "Source/File",
- "Read from any GnomeVFS-supported file",
- "Bastien Nocera <hadess@hadess.net>\n"
- "Ronald S. Bultje <rbultje@ronald.bitfreak.net>");
-
-static GStaticMutex count_lock = G_STATIC_MUTEX_INIT;
-static gint ref_count = 0;
-static gboolean vfs_owner = FALSE;
-
-static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-enum
-{
- ARG_0,
- ARG_HANDLE,
- ARG_LOCATION,
- ARG_IRADIO_MODE,
- ARG_IRADIO_NAME,
- ARG_IRADIO_GENRE,
- ARG_IRADIO_URL,
- ARG_IRADIO_TITLE
-};
-
-static void gst_gnome_vfs_src_base_init (gpointer g_class);
-static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass);
-static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc);
-static void gst_gnome_vfs_src_finalize (GObject * object);
-static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface,
- gpointer iface_data);
-
-static void gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_check_get_range (GstBaseSrc * src);
-static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size);
-static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc,
- guint64 offset, guint size, GstBuffer ** buffer);
-
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_gnome_vfs_src_get_type (void)
-{
- static GType gnomevfssrc_type = 0;
-
- if (!gnomevfssrc_type) {
- static const GTypeInfo gnomevfssrc_info = {
- sizeof (GstGnomeVFSSrcClass),
- gst_gnome_vfs_src_base_init,
- NULL,
- (GClassInitFunc) gst_gnome_vfs_src_class_init,
- NULL,
- NULL,
- sizeof (GstGnomeVFSSrc),
- 0,
- (GInstanceInitFunc) gst_gnome_vfs_src_init,
- };
- static const GInterfaceInfo urihandler_info = {
- gst_gnome_vfs_src_uri_handler_init,
- NULL,
- NULL
- };
-
- gnomevfssrc_type =
- g_type_register_static (GST_TYPE_BASE_SRC,
- "GstGnomeVFSSrc", &gnomevfssrc_info, 0);
- g_type_add_interface_static (gnomevfssrc_type, GST_TYPE_URI_HANDLER,
- &urihandler_info);
- }
- return gnomevfssrc_type;
-}
-
-static void
-gst_gnome_vfs_src_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&srctemplate));
- gst_element_class_set_details (element_class, &gst_gnome_vfs_src_details);
-
- GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0,
- "Gnome-VFS Source");
-}
-
-static void
-gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
- gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_gnome_vfs_src_finalize;
- gobject_class->set_property = gst_gnome_vfs_src_set_property;
- gobject_class->get_property = gst_gnome_vfs_src_get_property;
-
- /* properties */
- gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass),
- "location", ARG_LOCATION, G_PARAM_READWRITE, NULL);
- g_object_class_install_property (gobject_class,
- ARG_HANDLE,
- g_param_spec_boxed ("handle",
- "GnomeVFSHandle", "Handle for GnomeVFS",
- GST_TYPE_GNOME_VFS_HANDLE, G_PARAM_READWRITE));
-
- /* icecast stuff */
- g_object_class_install_property (gobject_class,
- ARG_IRADIO_MODE,
- g_param_spec_boolean ("iradio-mode",
- "iradio-mode",
- "Enable internet radio mode (extraction of shoutcast/icecast metadata)",
- FALSE, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class,
- ARG_IRADIO_NAME,
- g_param_spec_string ("iradio-name",
- "iradio-name", "Name of the stream", NULL, G_PARAM_READABLE));
- g_object_class_install_property (gobject_class,
- ARG_IRADIO_GENRE,
- g_param_spec_string ("iradio-genre",
- "iradio-genre", "Genre of the stream", NULL, G_PARAM_READABLE));
- g_object_class_install_property (gobject_class,
- ARG_IRADIO_URL,
- g_param_spec_string ("iradio-url",
- "iradio-url",
- "Homepage URL for radio stream", NULL, G_PARAM_READABLE));
- g_object_class_install_property (gobject_class,
- ARG_IRADIO_TITLE,
- g_param_spec_string ("iradio-title",
- "iradio-title",
- "Name of currently playing song", NULL, G_PARAM_READABLE));
-
- gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start);
- gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop);
- gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size);
- gstbasesrc_class->is_seekable =
- GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable);
- gstbasesrc_class->check_get_range =
- GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_check_get_range);
- gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create);
-}
-
-static void
-gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc)
-{
- gnomevfssrc->uri = NULL;
- gnomevfssrc->uri_name = NULL;
- gnomevfssrc->handle = NULL;
- gnomevfssrc->curoffset = 0;
- gnomevfssrc->seekable = FALSE;
-
- gnomevfssrc->icy_caps = NULL;
- gnomevfssrc->iradio_mode = FALSE;
- gnomevfssrc->http_callbacks_pushed = FALSE;
- gnomevfssrc->iradio_name = NULL;
- gnomevfssrc->iradio_genre = NULL;
- gnomevfssrc->iradio_url = NULL;
- gnomevfssrc->iradio_title = NULL;
-
- g_static_mutex_lock (&count_lock);
- if (ref_count == 0) {
- /* gnome vfs engine init */
- if (gnome_vfs_initialized () == FALSE) {
- gnome_vfs_init ();
- vfs_owner = TRUE;
- }
- }
- ref_count++;
- g_static_mutex_unlock (&count_lock);
-}
-
-static void
-gst_gnome_vfs_src_finalize (GObject * object)
-{
- GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (object);
-
- g_static_mutex_lock (&count_lock);
- ref_count--;
- if (ref_count == 0 && vfs_owner) {
- if (gnome_vfs_initialized () == TRUE) {
- gnome_vfs_shutdown ();
- }
- }
- g_static_mutex_unlock (&count_lock);
-
- if (src->uri) {
- gnome_vfs_uri_unref (src->uri);
- src->uri = NULL;
- }
-
- g_free (src->uri_name);
- src->uri_name = NULL;
-
- g_free (src->iradio_name);
- src->iradio_name = NULL;
-
- g_free (src->iradio_genre);
- src->iradio_genre = NULL;
-
- g_free (src->iradio_url);
- src->iradio_url = NULL;
-
- g_free (src->iradio_title);
- src->iradio_title = NULL;
-
- if (src->icy_caps) {
- gst_caps_unref (src->icy_caps);
- src->icy_caps = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/*
- * URI interface support.
- */
-
-static GstURIType
-gst_gnome_vfs_src_uri_get_type (void)
-{
- return GST_URI_SRC;
-}
-
-static gchar **
-gst_gnome_vfs_src_uri_get_protocols (void)
-{
- static gchar **protocols = NULL;
-
- if (!protocols)
- protocols = gst_gnomevfs_get_supported_uris ();
-
- return protocols;
-}
-
-static const gchar *
-gst_gnome_vfs_src_uri_get_uri (GstURIHandler * handler)
-{
- GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
-
- return src->uri_name;
-}
-
-static gboolean
-gst_gnome_vfs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
-{
- GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler);
-
- if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
- return FALSE;
-
- g_object_set (G_OBJECT (src), "location", uri, NULL);
-
- return TRUE;
-}
-
-static void
-gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
-{
- GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
-
- iface->get_type = gst_gnome_vfs_src_uri_get_type;
- iface->get_protocols = gst_gnome_vfs_src_uri_get_protocols;
- iface->get_uri = gst_gnome_vfs_src_uri_get_uri;
- iface->set_uri = gst_gnome_vfs_src_uri_set_uri;
-}
-
-static void
-gst_gnome_vfs_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (object);
-
- switch (prop_id) {
- case ARG_LOCATION:{
- const gchar *new_location;
-
- /* the element must be stopped or paused in order to do this */
- if (GST_STATE (src) == GST_STATE_PLAYING ||
- GST_STATE (src) == GST_STATE_PAUSED)
- break;
-
- if (src->uri) {
- gnome_vfs_uri_unref (src->uri);
- src->uri = NULL;
- }
- if (src->uri_name) {
- g_free (src->uri_name);
- src->uri_name = NULL;
- }
-
- new_location = g_value_get_string (value);
- if (new_location) {
- src->uri_name = gst_gnome_vfs_location_to_uri_string (new_location);
- src->uri = gnome_vfs_uri_new (src->uri_name);
- }
- break;
- }
- case ARG_HANDLE:
- if (GST_STATE (src) == GST_STATE_NULL ||
- GST_STATE (src) == GST_STATE_READY) {
- if (src->uri) {
- gnome_vfs_uri_unref (src->uri);
- src->uri = NULL;
- }
- if (src->uri_name) {
- g_free (src->uri_name);
- src->uri_name = NULL;
- }
- src->handle = g_value_get_boxed (value);
- }
- break;
- case ARG_IRADIO_MODE:
- src->iradio_mode = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (object);
-
- switch (prop_id) {
- case ARG_LOCATION:
- g_value_set_string (value, src->uri_name);
- break;
- case ARG_HANDLE:
- g_value_set_boxed (value, src->handle);
- break;
- case ARG_IRADIO_MODE:
- g_value_set_boolean (value, src->iradio_mode);
- break;
- case ARG_IRADIO_NAME:
- g_value_set_string (value, src->iradio_name);
- break;
- case ARG_IRADIO_GENRE:
- g_value_set_string (value, src->iradio_genre);
- break;
- case ARG_IRADIO_URL:
- g_value_set_string (value, src->iradio_url);
- break;
- case ARG_IRADIO_TITLE:
- g_value_set_string (value, src->iradio_title);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static char *
-gst_gnome_vfs_src_unicodify (const char *str)
-{
- const gchar *env_vars[] = { "GST_ICY_TAG_ENCODING",
- "GST_TAG_ENCODING", NULL
- };
-
- return gst_tag_freeform_string_to_utf8 (str, -1, env_vars);
-}
-
-static void
-gst_gnome_vfs_src_send_additional_headers_callback (gconstpointer in,
- gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
-{
- GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
- GnomeVFSModuleCallbackAdditionalHeadersOut *out_args =
- (GnomeVFSModuleCallbackAdditionalHeadersOut *) out;
-
- if (!src->iradio_mode)
- return;
- GST_DEBUG_OBJECT (src, "sending headers\n");
-
- out_args->headers = g_list_append (out_args->headers,
- g_strdup ("icy-metadata:1\r\n"));
-}
-
-static void
-gst_gnome_vfs_src_received_headers_callback (gconstpointer in,
- gsize in_size, gpointer out, gsize out_size, gpointer callback_data)
-{
- GList *i;
- gint icy_metaint;
- GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data);
- GnomeVFSModuleCallbackReceivedHeadersIn *in_args =
- (GnomeVFSModuleCallbackReceivedHeadersIn *) in;
-
- /* This is only used for internet radio stuff right now */
- if (!src->iradio_mode)
- return;
-
- for (i = in_args->headers; i; i = i->next) {
- char *data = (char *) i->data;
- char *key = data;
- char *value = strchr (data, ':');
-
- if (!value)
- continue;
-
- value++;
- g_strstrip (value);
- if (!strlen (value))
- continue;
-
- /* Icecast stuff */
- if (strncmp (data, "icy-metaint:", 12) == 0) { /* ugh */
- if (sscanf (data + 12, "%d", &icy_metaint) == 1) {
- if (icy_metaint > 0)
- src->icy_caps = gst_caps_new_simple ("application/x-icy",
- "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
- }
- continue;
- }
-
- if (!strncmp (data, "icy-", 4))
- key = data + 4;
- else
- continue;
-
- GST_DEBUG_OBJECT (src, "key: %s", key);
- if (!strncmp (key, "name", 4)) {
- g_free (src->iradio_name);
- src->iradio_name = gst_gnome_vfs_src_unicodify (value);
- if (src->iradio_name)
- g_object_notify (G_OBJECT (src), "iradio-name");
- } else if (!strncmp (key, "genre", 5)) {
- g_free (src->iradio_genre);
- src->iradio_genre = gst_gnome_vfs_src_unicodify (value);
- if (src->iradio_genre)
- g_object_notify (G_OBJECT (src), "iradio-genre");
- } else if (!strncmp (key, "url", 3)) {
- g_free (src->iradio_url);
- src->iradio_url = gst_gnome_vfs_src_unicodify (value);
- if (src->iradio_url)
- g_object_notify (G_OBJECT (src), "iradio-url");
- }
- }
-}
-
-static void
-gst_gnome_vfs_src_push_callbacks (GstGnomeVFSSrc * src)
-{
- if (src->http_callbacks_pushed)
- return;
-
- GST_DEBUG_OBJECT (src, "pushing callbacks");
- gnome_vfs_module_callback_push
- (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS,
- gst_gnome_vfs_src_send_additional_headers_callback, src, NULL);
- gnome_vfs_module_callback_push
- (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS,
- gst_gnome_vfs_src_received_headers_callback, src, NULL);
-
- src->http_callbacks_pushed = TRUE;
-}
-
-static void
-gst_gnome_vfs_src_pop_callbacks (GstGnomeVFSSrc * src)
-{
- if (!src->http_callbacks_pushed)
- return;
-
- GST_DEBUG_OBJECT (src, "popping callbacks");
- gnome_vfs_module_callback_pop
- (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS);
- gnome_vfs_module_callback_pop
- (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS);
-
- src->http_callbacks_pushed = FALSE;
-}
-
-/*
- * Read a new buffer from src->reqoffset, takes care of events
- * and seeking and such.
- */
-static GstFlowReturn
-gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size,
- GstBuffer ** buffer)
-{
- GnomeVFSResult res;
- GstBuffer *buf;
- GnomeVFSFileSize readbytes;
- guint8 *data;
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- GST_DEBUG ("now at %llu, reading from %lld, size %u", src->curoffset, offset,
- size);
-
- /* seek if required */
- if (G_UNLIKELY (src->curoffset != offset)) {
- GST_DEBUG ("need to seek");
- if (src->seekable) {
- GST_DEBUG ("seeking to %lld", offset);
- res = gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_START, offset);
- if (res != GNOME_VFS_OK)
- goto seek_failed;
- src->curoffset = offset;
- } else {
- goto cannot_seek;
- }
- }
-
- buf = gst_buffer_new_and_alloc (size);
-
- if (src->icy_caps)
- gst_buffer_set_caps (buf, src->icy_caps);
-
- data = GST_BUFFER_DATA (buf);
- GST_BUFFER_OFFSET (buf) = src->curoffset;
-
- res = gnome_vfs_read (src->handle, data, size, &readbytes);
-
- if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK
- && readbytes == 0)))
- goto eos;
-
- GST_BUFFER_SIZE (buf) = readbytes;
-
- if (G_UNLIKELY (res != GNOME_VFS_OK))
- goto read_failed;
-
- src->curoffset += readbytes;
-
- /* we're done, return the buffer */
- *buffer = buf;
-
- return GST_FLOW_OK;
-
-seek_failed:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
- ("Failed to seek to requested position %" G_GINT64_FORMAT ": %s",
- offset, gnome_vfs_result_to_string (res)));
- return GST_FLOW_ERROR;
- }
-cannot_seek:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL),
- ("Requested seek from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT
- " on non-seekable stream", src->curoffset, offset));
- return GST_FLOW_ERROR;
- }
-read_failed:
- {
- gst_buffer_unref (buf);
- GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
- ("Failed to read data: %s", gnome_vfs_result_to_string (res)));
- return GST_FLOW_ERROR;
- }
-eos:
- {
- gst_buffer_unref (buf);
- GST_DEBUG_OBJECT (src, "Reading data gave EOS");
- return GST_FLOW_UNEXPECTED;
- }
-}
-
-static gboolean
-gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc)
-{
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- return src->seekable;
-}
-
-static gboolean
-gst_gnome_vfs_src_check_get_range (GstBaseSrc * basesrc)
-{
- GstGnomeVFSSrc *src;
- const gchar *protocol;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- if (src->uri == NULL) {
- GST_WARNING_OBJECT (src, "no URI set yet");
- return FALSE;
- }
-
- if (gnome_vfs_uri_is_local (src->uri)) {
- GST_LOG_OBJECT (src, "local URI (%s), assuming random access is possible",
- GST_STR_NULL (src->uri_name));
- return TRUE;
- }
-
- /* blacklist certain protocols we know won't work getrange-based */
- protocol = gnome_vfs_uri_get_scheme (src->uri);
- if (protocol == NULL)
- goto undecided;
-
- if (strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0) {
- GST_LOG_OBJECT (src, "blacklisted protocol '%s', no random access possible"
- " (URI=%s)", protocol, GST_STR_NULL (src->uri_name));
- return FALSE;
- }
-
- /* fall through to undecided */
-
-undecided:
- {
- /* don't know what to do, let the basesrc class decide for us */
- GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it",
- GST_STR_NULL (src->uri_name));
-
- if (GST_BASE_SRC_CLASS (parent_class)->check_get_range)
- return GST_BASE_SRC_CLASS (parent_class)->check_get_range (basesrc);
-
- return FALSE;
- }
-}
-
-static gboolean
-gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size)
-{
- GstGnomeVFSSrc *src;
- GnomeVFSFileInfo *info;
- GnomeVFSFileInfoOptions options;
- GnomeVFSResult res;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- *size = -1;
- info = gnome_vfs_file_info_new ();
- options = GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS;
- res = gnome_vfs_get_file_info_from_handle (src->handle, info, options);
- if (res == GNOME_VFS_OK) {
- if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
- *size = info->size;
- GST_DEBUG_OBJECT (src, "from handle: %" G_GUINT64_FORMAT " bytes", *size);
- } else if (src->own_handle && gnome_vfs_uri_is_local (src->uri)) {
- GST_DEBUG_OBJECT (src,
- "file size not known, file local, trying fallback");
- res = gnome_vfs_get_file_info_uri (src->uri, info, options);
- if (res == GNOME_VFS_OK &&
- (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) {
- *size = info->size;
- GST_DEBUG_OBJECT (src, "from uri: %" G_GUINT64_FORMAT " bytes", *size);
- }
- }
- } else {
- GST_WARNING_OBJECT (src, "getting info failed: %s",
- gnome_vfs_result_to_string (res));
- }
- gnome_vfs_file_info_unref (info);
-
- if (*size == (GnomeVFSFileSize) - 1)
- return FALSE;
-
- GST_DEBUG_OBJECT (src, "return size %" G_GUINT64_FORMAT, *size);
-
- return TRUE;
-}
-
-/* open the file, do stuff necessary to go to PAUSED state */
-static gboolean
-gst_gnome_vfs_src_start (GstBaseSrc * basesrc)
-{
- GnomeVFSResult res;
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- gst_gnome_vfs_src_push_callbacks (src);
-
- if (src->uri != NULL) {
- GnomeVFSOpenMode mode = GNOME_VFS_OPEN_READ;
-
- /* this can block... */
- res = gnome_vfs_open_uri (&src->handle, src->uri, mode);
- if (res != GNOME_VFS_OK)
- goto open_failed;
- src->own_handle = TRUE;
- } else if (!src->handle) {
- goto no_filename;
- } else {
- src->own_handle = FALSE;
- }
-
- if (gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_CURRENT, 0) == GNOME_VFS_OK) {
- src->seekable = TRUE;
- } else {
- src->seekable = FALSE;
- }
-
- return TRUE;
-
- /* ERRORS */
-open_failed:
- {
- gchar *filename = gnome_vfs_uri_to_string (src->uri,
- GNOME_VFS_URI_HIDE_PASSWORD);
-
- gst_gnome_vfs_src_pop_callbacks (src);
-
- if (res == GNOME_VFS_ERROR_NOT_FOUND ||
- res == GNOME_VFS_ERROR_HOST_NOT_FOUND ||
- res == GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE) {
- GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
- ("Could not open vfs file \"%s\" for reading: %s (%d)",
- filename, gnome_vfs_result_to_string (res), res));
- } else {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL),
- ("Could not open vfs file \"%s\" for reading: %s (%d)",
- filename, gnome_vfs_result_to_string (res), res));
- }
- g_free (filename);
- return FALSE;
- }
-no_filename:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given"));
- return FALSE;
- }
-}
-
-static gboolean
-gst_gnome_vfs_src_stop (GstBaseSrc * basesrc)
-{
- GstGnomeVFSSrc *src;
-
- src = GST_GNOME_VFS_SRC (basesrc);
-
- gst_gnome_vfs_src_pop_callbacks (src);
-
- if (src->own_handle) {
- GnomeVFSResult res;
-
- res = gnome_vfs_close (src->handle);
- if (res != GNOME_VFS_OK) {
- GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL),
- ("Could not close vfs handle: %s", gnome_vfs_result_to_string (res)));
- }
- src->handle = NULL;
- }
- src->curoffset = 0;
-
- if (src->icy_caps) {
- gst_caps_unref (src->icy_caps);
- src->icy_caps = NULL;
- }
-
- return TRUE;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfssrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2001 Bastien Nocera <hadess@hadess.net>
- * 2002 Kristian Rietveld <kris@gtk.org>
- * 2002,2003 Colin Walters <walters@gnu.org>
- *
- * 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 __GST_GNOME_VFS_SRC_H__
-#define __GST_GNOME_VFS_SRC_H__
-
-#include <gst/base/gstbasesrc.h>
-
-#include "gstgnomevfs.h"
-#include "gstgnomevfsuri.h"
-#include <libgnomevfs/gnome-vfs.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNOME_VFS_SRC \
- (gst_gnome_vfs_src_get_type())
-#define GST_GNOME_VFS_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrc))
-#define GST_GNOME_VFS_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrcClass))
-#define GST_IS_GNOME_VFS_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SRC))
-#define GST_IS_GNOME_VFS_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SRC))
-
-typedef struct _GstGnomeVFSSrc GstGnomeVFSSrc;
-typedef struct _GstGnomeVFSSrcClass GstGnomeVFSSrcClass;
-
-/**
- * GstGnomeVFSSrc:
- *
- * Opaque data structure.
- */
-struct _GstGnomeVFSSrc
-{
- GstBaseSrc basesrc;
-
- /* uri, file, ... */
- GnomeVFSURI *uri;
- gchar *uri_name;
- GnomeVFSHandle *handle;
- gboolean own_handle;
- GnomeVFSFileOffset curoffset; /* current offset in file */
- gboolean seekable;
-
- /* shoutcast/icecast metadata extraction handling */
- gboolean iradio_mode;
- gboolean http_callbacks_pushed;
-
- GstCaps *icy_caps;
-
- gchar *iradio_name;
- gchar *iradio_genre;
- gchar *iradio_url;
- gchar *iradio_title;
-};
-
-struct _GstGnomeVFSSrcClass
-{
- GstBaseSrcClass basesrc_class;
-};
-
-GType gst_gnome_vfs_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_SRC_H__ */
-
-
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/* GStreamer
- * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000 Wim Taymans <wtay@chello.be>
- * 2001 Bastien Nocera <hadess@hadess.net>
- * 2003 Colin Walters <walters@verbum.org>
- *
- * gstgnomevfssink.c:
- *
- * 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 <libgnomevfs/gnome-vfs.h>
-#include "gstgnomevfsuri.h"
-
-#include <gst/gst.h>
-
-gchar **
-gst_gnomevfs_get_supported_uris (void)
-{
- /* no dav/davs in the list, because they don't appear to be reliable enough */
- const gchar *uris[] = {
- "http://localhost/bla",
- "https://localhost/bla",
- "file:///bla",
- "smb://localhost/bla",
- "ftp://localhost/bla",
- "sftp://localhost/bla",
- "nfs://localhost/bla",
- "ssh://localhost/bla",
- "burn://"
- };
- GnomeVFSURI *uri;
- gchar **result;
- gint n, r = 0;
-
- result = g_new0 (gchar *, G_N_ELEMENTS (uris) + 1);
- for (n = 0; n < G_N_ELEMENTS (uris); n++) {
- uri = gnome_vfs_uri_new (uris[n]);
- if (uri != NULL) {
- gchar *protocol = g_strdup (uris[n]);
- gint n;
-
- gnome_vfs_uri_unref (uri);
- for (n = 0; protocol[n] != '\0'; n++) {
- if (protocol[n] == ':') {
- protocol[n] = '\0';
- break;
- }
- }
-
- GST_DEBUG ("adding protocol '%s'", protocol);
- result[r++] = protocol;
- } else {
- GST_DEBUG ("could not create GnomeVfsUri from '%s'", uris[n]);
- }
- }
- result[r] = NULL;
-
- return result;
-}
--- a/gst_plugins_base/ext/gnomevfs/gstgnomevfsuri.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/* GStreamer
- * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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 __GST_GNOME_VFS_URI_H__
-#define __GST_GNOME_VFS_URI_H__
-
-#include <libgnomevfs/gnome-vfs.h>
-
-G_BEGIN_DECLS
-
-gchar **gst_gnomevfs_get_supported_uris (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNOME_VFS_URI_H__ */
--- a/gst_plugins_base/ext/libvisual/visual.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,957 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
- *
- * 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 <gst/gst.h>
-#include <gst/base/gstadapter.h>
-#include <gst/video/video.h>
-#include <gst/audio/audio.h>
-#include <libvisual/libvisual.h>
-
-#define GST_TYPE_VISUAL (gst_visual_get_type())
-#define GST_IS_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VISUAL))
-#define GST_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VISUAL,GstVisual))
-#define GST_IS_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VISUAL))
-#define GST_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VISUAL,GstVisualClass))
-#define GST_VISUAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VISUAL, GstVisualClass))
-
-typedef struct _GstVisual GstVisual;
-typedef struct _GstVisualClass GstVisualClass;
-
-GST_DEBUG_CATEGORY_STATIC (libvisual_debug);
-#define GST_CAT_DEFAULT (libvisual_debug)
-
-struct _GstVisual
-{
- GstElement element;
-
- /* pads */
- GstPad *sinkpad;
- GstPad *srcpad;
- GstClockTime next_ts;
- GstSegment segment;
-
- /* libvisual stuff */
- VisAudio *audio;
- VisVideo *video;
- VisActor *actor;
-
- /* audio/video state */
- gint channels;
- gint rate; /* Input samplerate */
- gint bps;
-
- /* framerate numerator & denominator */
- gint fps_n;
- gint fps_d;
- gint width;
- gint height;
- GstClockTime duration;
- guint outsize;
-
- /* samples per frame based on caps */
- guint spf;
-
- /* state stuff */
- GstAdapter *adapter;
- guint count;
-
- /* QoS stuff *//* with LOCK */
- gdouble proportion;
- GstClockTime earliest_time;
-};
-
-struct _GstVisualClass
-{
- GstElementClass parent_class;
-
- VisPluginRef *plugin;
-};
-
-GType gst_visual_get_type (void);
-
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN "; "
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- GST_VIDEO_CAPS_RGB "; "
-#else
- GST_VIDEO_CAPS_BGR "; "
-#endif
- GST_VIDEO_CAPS_RGB_16)
- );
-
-static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-int, "
- "width = (int) 16, "
- "depth = (int) 16, "
- "endianness = (int) BYTE_ORDER, "
- "signed = (boolean) TRUE, " "channels = (int) { 1, 2 }, "
-#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
- "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }"
-#else
- "rate = (int) [ 1000, MAX ]"
-#endif
- )
- );
-
-
-static void gst_visual_class_init (gpointer g_class, gpointer class_data);
-static void gst_visual_init (GstVisual * visual);
-static void gst_visual_dispose (GObject * object);
-
-static GstStateChangeReturn gst_visual_change_state (GstElement * element,
- GstStateChange transition);
-static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_visual_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_visual_src_event (GstPad * pad, GstEvent * event);
-
-static gboolean gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_visual_src_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_visual_getcaps (GstPad * pad);
-static void libvisual_log_handler (const char *message, const char *funcname,
- void *priv);
-
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_visual_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo info = {
- sizeof (GstVisualClass),
- NULL,
- NULL,
- gst_visual_class_init,
- NULL,
- NULL,
- sizeof (GstVisual),
- 0,
- (GInstanceInitFunc) gst_visual_init,
- };
-
- type = g_type_register_static (GST_TYPE_ELEMENT, "GstVisual", &info, 0);
- }
- return type;
-}
-
-static void
-libvisual_log_handler (const char *message, const char *funcname, void *priv)
-{
- GST_CAT_LEVEL_LOG (libvisual_debug, (GstDebugLevel) (priv), NULL, "%s - %s",
- funcname, message);
-}
-
-static void
-gst_visual_class_init (gpointer g_class, gpointer class_data)
-{
- GstVisualClass *klass = GST_VISUAL_CLASS (g_class);
- GstElementClass *element = GST_ELEMENT_CLASS (g_class);
- GObjectClass *object = G_OBJECT_CLASS (g_class);
-
- klass->plugin = class_data;
-
- element->change_state = gst_visual_change_state;
-
- if (class_data == NULL) {
- parent_class = g_type_class_peek_parent (g_class);
- } else {
- GstElementDetails details = {
- NULL,
- "Visualization",
- klass->plugin->info->about,
- "Benjamin Otte <otte@gnome.org>"
- };
-
- details.longname = g_strdup_printf ("libvisual %s plugin v.%s",
- klass->plugin->info->name, klass->plugin->info->version);
-
- /* FIXME: improve to only register what plugin supports? */
- gst_element_class_add_pad_template (element,
- gst_static_pad_template_get (&src_template));
- gst_element_class_add_pad_template (element,
- gst_static_pad_template_get (&sink_template));
- gst_element_class_set_details (element, &details);
- g_free (details.longname);
- }
-
- object->dispose = gst_visual_dispose;
-}
-
-static void
-gst_visual_init (GstVisual * visual)
-{
- /* create the sink and src pads */
- visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
- gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_sink_setcaps);
- gst_pad_set_chain_function (visual->sinkpad, gst_visual_chain);
- gst_pad_set_event_function (visual->sinkpad, gst_visual_sink_event);
- gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad);
-
- visual->srcpad = gst_pad_new_from_static_template (&src_template, "src");
- gst_pad_set_setcaps_function (visual->srcpad, gst_visual_src_setcaps);
- gst_pad_set_getcaps_function (visual->srcpad, gst_visual_getcaps);
- gst_pad_set_event_function (visual->srcpad, gst_visual_src_event);
- gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad);
-
- visual->adapter = gst_adapter_new ();
-}
-
-static void
-gst_visual_clear_actors (GstVisual * visual)
-{
- if (visual->actor) {
- visual_object_unref (VISUAL_OBJECT (visual->actor));
- visual->actor = NULL;
- }
- if (visual->video) {
- visual_object_unref (VISUAL_OBJECT (visual->video));
- visual->video = NULL;
- }
- if (visual->audio) {
- visual_object_unref (VISUAL_OBJECT (visual->audio));
- visual->audio = NULL;
- }
-}
-
-static void
-gst_visual_dispose (GObject * object)
-{
- GstVisual *visual = GST_VISUAL (object);
-
- if (visual->adapter) {
- g_object_unref (visual->adapter);
- visual->adapter = NULL;
- }
- gst_visual_clear_actors (visual);
-
- GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
-}
-
-static void
-gst_visual_reset (GstVisual * visual)
-{
- visual->next_ts = -1;
- gst_adapter_clear (visual->adapter);
- gst_segment_init (&visual->segment, GST_FORMAT_UNDEFINED);
-
- GST_OBJECT_LOCK (visual);
- visual->proportion = 1.0;
- visual->earliest_time = -1;
- GST_OBJECT_UNLOCK (visual);
-}
-
-static GstCaps *
-gst_visual_getcaps (GstPad * pad)
-{
- GstCaps *ret;
- GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
- int depths;
-
- if (!visual->actor) {
- ret = gst_caps_copy (gst_pad_get_pad_template_caps (visual->srcpad));
- goto beach;
- }
-
- ret = gst_caps_new_empty ();
- depths = visual_actor_get_supported_depth (visual->actor);
- if (depths < 0) {
- /* FIXME: set an error */
- goto beach;
- }
- if (depths == VISUAL_VIDEO_DEPTH_GL) {
- /* We can't handle GL only plugins */
- goto beach;
- }
-
- GST_DEBUG_OBJECT (visual, "libvisual plugin supports depths %u (0x%04x)",
- depths, depths);
- /* if (depths & VISUAL_VIDEO_DEPTH_32BIT) Always supports 32bit output */
- gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN));
-
- if (depths & VISUAL_VIDEO_DEPTH_24BIT) {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB));
-#else
- gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_BGR));
-#endif
- }
- if (depths & VISUAL_VIDEO_DEPTH_16BIT) {
- gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB_16));
- }
-
-beach:
-
- GST_DEBUG_OBJECT (visual, "returning caps %" GST_PTR_FORMAT, ret);
- gst_object_unref (visual);
- return ret;
-}
-
-static gboolean
-gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
- GstStructure *structure;
- gint depth, pitch;
-
- structure = gst_caps_get_structure (caps, 0);
-
- GST_DEBUG_OBJECT (visual, "src pad got caps %" GST_PTR_FORMAT, caps);
-
- if (!gst_structure_get_int (structure, "width", &visual->width))
- goto error;
- if (!gst_structure_get_int (structure, "height", &visual->height))
- goto error;
- if (!gst_structure_get_int (structure, "bpp", &depth))
- goto error;
- if (!gst_structure_get_fraction (structure, "framerate", &visual->fps_n,
- &visual->fps_d))
- goto error;
-
- visual_video_set_depth (visual->video,
- visual_video_depth_enum_from_value (depth));
- visual_video_set_dimension (visual->video, visual->width, visual->height);
- pitch = GST_ROUND_UP_4 (visual->width * visual->video->bpp);
- visual_video_set_pitch (visual->video, pitch);
- visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
-
- /* precalc some values */
- visual->outsize = visual->video->height * pitch;
- visual->spf =
- gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
- visual->duration =
- gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n);
-
- gst_object_unref (visual);
- return TRUE;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (visual, "error parsing caps");
- gst_object_unref (visual);
- return FALSE;
- }
-}
-
-static gboolean
-gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
- GstStructure *structure;
-
- structure = gst_caps_get_structure (caps, 0);
-
- gst_structure_get_int (structure, "channels", &visual->channels);
- gst_structure_get_int (structure, "rate", &visual->rate);
-
- /* this is how many samples we need to fill one frame at the requested
- * framerate. */
- if (visual->fps_n != 0) {
- visual->spf =
- gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
- }
- visual->bps = visual->channels * sizeof (gint16);
-
- gst_object_unref (visual);
- return TRUE;
-}
-
-static gboolean
-gst_vis_src_negotiate (GstVisual * visual)
-{
- GstCaps *othercaps, *target, *intersect;
- GstStructure *structure;
- GstCaps *caps;
-
- caps = gst_pad_get_caps (visual->srcpad);
-
- /* see what the peer can do */
- othercaps = gst_pad_peer_get_caps (visual->srcpad);
- if (othercaps) {
- intersect = gst_caps_intersect (othercaps, caps);
- gst_caps_unref (othercaps);
- gst_caps_unref (caps);
-
- if (gst_caps_is_empty (intersect))
- goto no_format;
-
- target = gst_caps_copy_nth (intersect, 0);
- gst_caps_unref (intersect);
- } else {
- /* need a copy, we'll be modifying it when fixating */
- target = gst_caps_copy (caps);
- gst_caps_unref (caps);
- }
-
- /* fixate in case something is not fixed. This does nothing if the value is
- * already fixed. For video we always try to fixate to something like
- * 320x240x30 by convention. */
- structure = gst_caps_get_structure (target, 0);
- gst_structure_fixate_field_nearest_int (structure, "width", 320);
- gst_structure_fixate_field_nearest_int (structure, "height", 240);
- gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
-
- gst_pad_set_caps (visual->srcpad, target);
- gst_caps_unref (target);
-
- return TRUE;
-
- /* ERRORS */
-no_format:
- {
- GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
- ("could not negotiate output format"));
- gst_caps_unref (intersect);
- return FALSE;
- }
-}
-
-static gboolean
-gst_visual_sink_event (GstPad * pad, GstEvent * event)
-{
- GstVisual *visual;
- gboolean res;
-
- visual = GST_VISUAL (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- res = gst_pad_push_event (visual->srcpad, event);
- break;
- case GST_EVENT_FLUSH_STOP:
- /* reset QoS and adapter. */
- gst_visual_reset (visual);
- res = gst_pad_push_event (visual->srcpad, event);
- break;
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat format;
- gdouble rate, arate;
- gint64 start, stop, time;
- gboolean update;
-
- /* the newsegment values are used to clip the input samples
- * and to convert the incomming timestamps to running time so
- * we can do QoS */
- gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
- &start, &stop, &time);
-
- /* now configure the values */
- gst_segment_set_newsegment_full (&visual->segment, update,
- rate, arate, format, start, stop, time);
-
- /* and forward */
- res = gst_pad_push_event (visual->srcpad, event);
- break;
- }
- default:
- res = gst_pad_push_event (visual->srcpad, event);
- break;
- }
-
- gst_object_unref (visual);
- return res;
-}
-
-static gboolean
-gst_visual_src_event (GstPad * pad, GstEvent * event)
-{
- GstVisual *visual;
- gboolean res;
-
- visual = GST_VISUAL (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_QOS:
- {
- gdouble proportion;
- GstClockTimeDiff diff;
- GstClockTime timestamp;
-
- gst_event_parse_qos (event, &proportion, &diff, ×tamp);
-
- /* save stuff for the _chain function */
- GST_OBJECT_LOCK (visual);
- visual->proportion = proportion;
- if (diff >= 0)
- /* we're late, this is a good estimate for next displayable
- * frame (see part-qos.txt) */
- visual->earliest_time = timestamp + 2 * diff + visual->duration;
- else
- visual->earliest_time = timestamp + diff;
-
- GST_OBJECT_UNLOCK (visual);
-
- res = gst_pad_push_event (visual->sinkpad, event);
- break;
- }
- default:
- res = gst_pad_push_event (visual->sinkpad, event);
- break;
- }
-
- gst_object_unref (visual);
- return res;
-}
-
-/* allocate and output buffer, if no format was negotiated, this
- * function will negotiate one. After calling this function, a
- * reverse negotiation could have happened. */
-static GstFlowReturn
-get_buffer (GstVisual * visual, GstBuffer ** outbuf)
-{
- GstFlowReturn ret;
-
- /* we don't know an output format yet, pick one */
- if (GST_PAD_CAPS (visual->srcpad) == NULL) {
- if (!gst_vis_src_negotiate (visual))
- return GST_FLOW_NOT_NEGOTIATED;
- }
-
- GST_DEBUG_OBJECT (visual, "allocating output buffer with caps %"
- GST_PTR_FORMAT, GST_PAD_CAPS (visual->srcpad));
-
- /* now allocate a buffer with the last negotiated format.
- * Downstream could renegotiate a new format, which will trigger
- * our setcaps function on the source pad. */
- ret =
- gst_pad_alloc_buffer_and_set_caps (visual->srcpad,
- GST_BUFFER_OFFSET_NONE, visual->outsize,
- GST_PAD_CAPS (visual->srcpad), outbuf);
-
- /* no buffer allocated, we don't care why. */
- if (ret != GST_FLOW_OK)
- return ret;
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-gst_visual_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstBuffer *outbuf = NULL;
- guint i;
- GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
- GstFlowReturn ret = GST_FLOW_OK;
- guint avail;
-
- GST_DEBUG_OBJECT (visual, "chain function called");
-
- /* If we don't have an output format yet, preallocate a buffer to try and
- * set one */
- if (GST_PAD_CAPS (visual->srcpad) == NULL) {
- ret = get_buffer (visual, &outbuf);
- if (ret != GST_FLOW_OK) {
- gst_buffer_unref (buffer);
- goto beach;
- }
- }
-
- /* resync on DISCONT */
- if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
- gst_adapter_clear (visual->adapter);
- visual->next_ts = -1;
- }
-
- /* Match timestamps from the incoming audio */
- if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
- visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
-
- GST_DEBUG_OBJECT (visual,
- "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
- GST_BUFFER_SIZE (buffer) / visual->bps, GST_BUFFER_TIMESTAMP (buffer));
-
- gst_adapter_push (visual->adapter, buffer);
-
- while (TRUE) {
- gboolean need_skip;
- const guint16 *data;
-
- GST_DEBUG_OBJECT (visual, "processing buffer");
-
- avail = gst_adapter_available (visual->adapter);
- GST_DEBUG_OBJECT (visual, "avail now %u", avail);
-
- /* we need at least 512 samples */
- if (avail < 512 * visual->bps)
- break;
-
- /* we need at least enough samples to make one frame */
- if (avail < visual->spf * visual->bps)
- break;
-
- if (visual->next_ts != -1) {
- gint64 qostime;
-
- /* QoS is done on running time */
- qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME,
- visual->next_ts);
-
- GST_OBJECT_LOCK (visual);
- /* check for QoS, don't compute buffers that are known to be late */
- need_skip = visual->earliest_time != -1 &&
- qostime <= visual->earliest_time;
- GST_OBJECT_UNLOCK (visual);
-
- if (need_skip) {
- GST_WARNING_OBJECT (visual,
- "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time));
- goto skip;
- }
- }
-
- /* Read 512 samples per channel */
- data =
- (const guint16 *) gst_adapter_peek (visual->adapter, 512 * visual->bps);
-
-#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
- {
- VisBuffer *lbuf, *rbuf;
- guint16 ldata[512], rdata[512];
- VisAudioSampleRateType rate;
-
- lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL);
- rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL);
-
- if (visual->channels == 2) {
- for (i = 0; i < 512; i++) {
- ldata[i] = *data++;
- rdata[i] = *data++;
- }
- } else {
- for (i = 0; i < 512; i++) {
- ldata[i] = *data;
- rdata[i] = *data++;
- }
- }
-
- switch (visual->rate) {
- case 8000:
- rate = VISUAL_AUDIO_SAMPLE_RATE_8000;
- break;
- case 11250:
- rate = VISUAL_AUDIO_SAMPLE_RATE_11250;
- break;
- case 22500:
- rate = VISUAL_AUDIO_SAMPLE_RATE_22500;
- break;
- case 32000:
- rate = VISUAL_AUDIO_SAMPLE_RATE_32000;
- break;
- case 44100:
- rate = VISUAL_AUDIO_SAMPLE_RATE_44100;
- break;
- case 48000:
- rate = VISUAL_AUDIO_SAMPLE_RATE_48000;
- break;
- case 96000:
- rate = VISUAL_AUDIO_SAMPLE_RATE_96000;
- break;
- default:
- visual_object_unref (VISUAL_OBJECT (lbuf));
- visual_object_unref (VISUAL_OBJECT (rbuf));
- GST_ERROR_OBJECT (visual, "unsupported rate %d", visual->rate);
- ret = GST_FLOW_ERROR;
- goto beach;
- break;
- }
-
- visual_audio_samplepool_input_channel (visual->audio->samplepool,
- lbuf,
- rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_LEFT);
- visual_audio_samplepool_input_channel (visual->audio->samplepool,
- rbuf,
- rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, VISUAL_AUDIO_CHANNEL_RIGHT);
-
- visual_object_unref (VISUAL_OBJECT (lbuf));
- visual_object_unref (VISUAL_OBJECT (rbuf));
-
- }
-#else
- if (visual->channels == 2) {
- for (i = 0; i < 512; i++) {
- visual->audio->plugpcm[0][i] = *data++;
- visual->audio->plugpcm[1][i] = *data++;
- }
- } else {
- for (i = 0; i < 512; i++) {
- visual->audio->plugpcm[0][i] = *data;
- visual->audio->plugpcm[1][i] = *data++;
- }
- }
-#endif
-
- /* alloc a buffer if we don't have one yet, this happens
- * when we pushed a buffer in this while loop before */
- if (outbuf == NULL) {
- ret = get_buffer (visual, &outbuf);
- if (ret != GST_FLOW_OK) {
- goto beach;
- }
- }
- visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf));
- visual_audio_analyze (visual->audio);
- visual_actor_run (visual->actor, visual->audio);
- visual_video_set_buffer (visual->video, NULL);
- GST_DEBUG_OBJECT (visual, "rendered one frame");
-
- GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
- GST_BUFFER_DURATION (outbuf) = visual->duration;
-
- ret = gst_pad_push (visual->srcpad, outbuf);
- outbuf = NULL;
-
- skip:
- /* interpollate next timestamp */
- if (visual->next_ts != -1)
- visual->next_ts += visual->duration;
-
- GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
- visual->spf);
-
- /* Flush out the number of samples per frame */
- gst_adapter_flush (visual->adapter, visual->spf * visual->bps);
-
- /* quit the loop if something was wrong */
- if (ret != GST_FLOW_OK)
- break;
- }
-
-beach:
-
- if (outbuf != NULL)
- gst_buffer_unref (outbuf);
-
- gst_object_unref (visual);
-
- return ret;
-}
-
-static GstStateChangeReturn
-gst_visual_change_state (GstElement * element, GstStateChange transition)
-{
- GstVisual *visual = GST_VISUAL (element);
- GstStateChangeReturn ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- visual->actor =
- visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info->
- plugname);
- visual->video = visual_video_new ();
- visual->audio = visual_audio_new ();
- /* can't have a play without actors */
- if (!visual->actor || !visual->video)
- goto no_actors;
-
- if (visual_actor_realize (visual->actor) != 0)
- goto no_realize;
-
- visual_actor_set_video (visual->actor, visual->video);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_visual_reset (visual);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_visual_clear_actors (visual);
- break;
- default:
- break;
- }
-
- return ret;
-
- /* ERRORS */
-no_actors:
- {
- GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
- ("could not create actors"));
- gst_visual_clear_actors (visual);
- return GST_STATE_CHANGE_FAILURE;
- }
-no_realize:
- {
- GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
- ("could not realize actor"));
- gst_visual_clear_actors (visual);
- return GST_STATE_CHANGE_FAILURE;
- }
-}
-
-static void
-make_valid_name (char *name)
-{
- /*
- * Replace invalid chars with _ in the type name
- */
- static const gchar extra_chars[] = "-_+";
- gchar *p = name;
-
- for (; *p; p++) {
- int valid = ((p[0] >= 'A' && p[0] <= 'Z') ||
- (p[0] >= 'a' && p[0] <= 'z') ||
- (p[0] >= '0' && p[0] <= '9') || strchr (extra_chars, p[0]));
- if (!valid)
- *p = '_';
- }
-}
-
-static gboolean
-gst_visual_actor_plugin_is_gl (VisObject * plugin, const gchar * name)
-{
- gboolean is_gl;
- gint depth;
-
-#if !defined(VISUAL_API_VERSION)
-
- depth = VISUAL_PLUGIN_ACTOR (plugin)->depth;
- is_gl = (depth == VISUAL_VIDEO_DEPTH_GL);
-
-#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
-
- depth = VISUAL_ACTOR_PLUGIN (plugin)->vidoptions.depth;
- /* FIXME: how to figure this out correctly in 0.4? */
- is_gl = (depth & VISUAL_VIDEO_DEPTH_GL) == VISUAL_VIDEO_DEPTH_GL;
-
-#else
-# error what libvisual version is this?
-#endif
-
- if (!is_gl) {
- GST_DEBUG ("plugin %s is not a GL plugin (%d), registering", name, depth);
- } else {
- GST_DEBUG ("plugin %s is a GL plugin (%d), ignoring", name, depth);
- }
-
- return is_gl;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- guint i, count;
- VisList *list;
-
- GST_DEBUG_CATEGORY_INIT (libvisual_debug, "libvisual", 0,
- "libvisual audio visualisations");
-
- visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW);
- visual_log_set_info_handler (libvisual_log_handler, (void *) GST_LEVEL_INFO);
- visual_log_set_warning_handler (libvisual_log_handler,
- (void *) GST_LEVEL_WARNING);
- visual_log_set_critical_handler (libvisual_log_handler,
- (void *) GST_LEVEL_ERROR);
- visual_log_set_error_handler (libvisual_log_handler,
- (void *) GST_LEVEL_ERROR);
-
- if (!visual_is_initialized ())
- if (visual_init (NULL, NULL) != 0)
- return FALSE;
-
- list = visual_actor_get_list ();
-
-#if !defined(VISUAL_API_VERSION)
- count = visual_list_count (list);
-#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
- count = visual_collection_size (VISUAL_COLLECTION (list));
-#endif
-
- for (i = 0; i < count; i++) {
- VisPluginRef *ref = visual_list_get (list, i);
- VisPluginData *visplugin = NULL;
- gboolean skip = FALSE;
- GType type;
- gchar *name;
- GTypeInfo info = {
- sizeof (GstVisualClass),
- NULL,
- NULL,
- gst_visual_class_init,
- NULL,
- ref,
- sizeof (GstVisual),
- 0,
- NULL
- };
-
- visplugin = visual_plugin_load (ref);
-
- if (ref->info->plugname == NULL)
- continue;
-
- /* Blacklist some plugins */
- if (strcmp (ref->info->plugname, "gstreamer") == 0 ||
- strcmp (ref->info->plugname, "gdkpixbuf") == 0) {
- skip = TRUE;
- } else {
- /* Ignore plugins that only support GL output for now */
- skip = gst_visual_actor_plugin_is_gl (visplugin->info->plugin,
- visplugin->info->plugname);
- }
-
- visual_plugin_unload (visplugin);
-
- if (!skip) {
- name = g_strdup_printf ("GstVisual%s", ref->info->plugname);
- make_valid_name (name);
- type = g_type_register_static (GST_TYPE_VISUAL, name, &info, 0);
- g_free (name);
-
- name = g_strdup_printf ("libvisual_%s", ref->info->plugname);
- make_valid_name (name);
- if (!gst_element_register (plugin, name, GST_RANK_NONE, type)) {
- g_free (name);
- return FALSE;
- }
- g_free (name);
- }
- }
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "libvisual",
- "libvisual visualization plugins",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/ogg/gstogg.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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 <gst/gst.h>
-
-extern gboolean gst_ogg_demux_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_mux_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogm_parse_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_parse_plugin_init (GstPlugin * plugin);
-extern gboolean gst_ogg_avi_parse_plugin_init (GstPlugin * plugin);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- gst_ogg_demux_plugin_init (plugin);
- gst_ogg_mux_plugin_init (plugin);
- gst_ogm_parse_plugin_init (plugin);
- gst_ogg_parse_plugin_init (plugin);
- gst_ogg_avi_parse_plugin_init (plugin);
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "ogg",
- "ogg stream manipulation (info about ogg: http://xiph.org)",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/ogg/gstoggaviparse.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,478 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Wim Taymans <wim@fluendo.com>
- *
- * gstoggaviparse.c: ogg avi stream parser
- *
- * 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.
- */
-
-/*
- * Ogg in AVI is mostly done for vorbis audio. In the codec_data we receive the
- * first 3 packets of the raw vorbis data. On the sinkpad we receive full-blown Ogg
- * pages.
- * Before extracting the packets out of the ogg pages, we push the raw vorbis
- * header packets to the decoder.
- * We don't use the incomming timestamps but use the ganulepos on the ogg pages
- * directly.
- * This parser only does ogg/vorbis for now.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <gst/gst.h>
-#include <ogg/ogg.h>
-#include <string.h>
-
-static const GstElementDetails gst_ogg_avi_parse_details =
-GST_ELEMENT_DETAILS ("Ogg AVI parser",
- "Codec/Parser",
- "parse an ogg avi stream into pages (info about ogg: http://xiph.org)",
- "Wim Taymans <wim@fluendo.com>");
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_avi_parse_debug);
-#define GST_CAT_DEFAULT gst_ogg_avi_parse_debug
-
-#define GST_TYPE_OGG_AVI_PARSE (gst_ogg_avi_parse_get_type())
-#define GST_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
-#define GST_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse))
-#define GST_IS_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_AVI_PARSE))
-#define GST_IS_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_AVI_PARSE))
-
-static GType gst_ogg_avi_parse_get_type (void);
-
-typedef struct _GstOggAviParse GstOggAviParse;
-typedef struct _GstOggAviParseClass GstOggAviParseClass;
-
-struct _GstOggAviParse
-{
- GstElement element;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- gboolean discont;
- gint serial;
-
- ogg_sync_state sync;
- ogg_stream_state stream;
-};
-
-struct _GstOggAviParseClass
-{
- GstElementClass parent_class;
-};
-
-static void gst_ogg_avi_parse_base_init (gpointer g_class);
-static void gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass);
-static void gst_ogg_avi_parse_init (GstOggAviParse * ogg);
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogg_avi_parse_get_type (void)
-{
- static GType ogg_avi_parse_type = 0;
-
- if (!ogg_avi_parse_type) {
- static const GTypeInfo ogg_avi_parse_info = {
- sizeof (GstOggAviParseClass),
- gst_ogg_avi_parse_base_init,
- NULL,
- (GClassInitFunc) gst_ogg_avi_parse_class_init,
- NULL,
- NULL,
- sizeof (GstOggAviParse),
- 0,
- (GInstanceInitFunc) gst_ogg_avi_parse_init,
- };
-
- ogg_avi_parse_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstOggAviParse",
- &ogg_avi_parse_info, 0);
- }
- return ogg_avi_parse_type;
-}
-
-enum
-{
- PROP_0
-};
-
-static GstStaticPadTemplate ogg_avi_parse_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-vorbis")
- );
-
-static GstStaticPadTemplate ogg_avi_parse_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-ogg-avi")
- );
-
-static void gst_ogg_avi_parse_finalize (GObject * object);
-static GstStateChangeReturn gst_ogg_avi_parse_change_state (GstElement *
- element, GstStateChange transition);
-static gboolean gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps);
-
-static void
-gst_ogg_avi_parse_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_ogg_avi_parse_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_avi_parse_sink_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_avi_parse_src_template_factory));
-}
-
-static void
-gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gstelement_class->change_state = gst_ogg_avi_parse_change_state;
-
- gobject_class->finalize = gst_ogg_avi_parse_finalize;
-}
-
-static void
-gst_ogg_avi_parse_init (GstOggAviParse * ogg)
-{
- /* create the sink and source pads */
- ogg->sinkpad =
- gst_pad_new_from_static_template (&ogg_avi_parse_sink_template_factory,
- "sink");
- gst_pad_set_setcaps_function (ogg->sinkpad, gst_ogg_avi_parse_setcaps);
- gst_pad_set_event_function (ogg->sinkpad, gst_ogg_avi_parse_event);
- gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_avi_parse_chain);
- gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
-
- ogg->srcpad =
- gst_pad_new_from_static_template (&ogg_avi_parse_src_template_factory,
- "src");
- gst_pad_use_fixed_caps (ogg->srcpad);
- gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad);
-}
-
-static void
-gst_ogg_avi_parse_finalize (GObject * object)
-{
- GstOggAviParse *ogg = GST_OGG_AVI_PARSE (object);
-
- GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg);
-
- ogg_sync_clear (&ogg->sync);
- ogg_stream_clear (&ogg->stream);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstOggAviParse *ogg;
- GstStructure *structure;
- const GValue *codec_data;
- GstBuffer *buffer;
- guint8 *data;
- guint size;
- guint32 sizes[3];
- GstCaps *outcaps;
- gint i, offs;
-
- ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
- structure = gst_caps_get_structure (caps, 0);
-
- /* take codec data */
- codec_data = gst_structure_get_value (structure, "codec_data");
- if (codec_data == NULL)
- goto no_data;
-
- /* only buffers are valid */
- if (G_VALUE_TYPE (codec_data) != GST_TYPE_BUFFER)
- goto wrong_format;
-
- /* Now parse the data */
- buffer = gst_value_get_buffer (codec_data);
-
- /* first 22 bytes are bits_per_sample, channel_mask, GUID
- * Then we get 3 LE guint32 with the 3 header sizes
- * then we get the bytes of the 3 headers. */
- data = GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer);
-
- GST_LOG_OBJECT (ogg, "configuring codec_data of size %u", size);
-
- /* skip headers */
- data += 22;
- size -= 22;
-
- /* we need at least 12 bytes for the packet sizes of the 3 headers */
- if (size < 12)
- goto buffer_too_small;
-
- /* read sizes of the 3 headers */
- sizes[0] = GST_READ_UINT32_LE (data);
- sizes[1] = GST_READ_UINT32_LE (data + 4);
- sizes[2] = GST_READ_UINT32_LE (data + 8);
-
- GST_DEBUG_OBJECT (ogg, "header sizes: %u %u %u", sizes[0], sizes[1],
- sizes[2]);
-
- data += 12;
- size -= 12;
-
- /* and we need at least enough data for all the headers */
- if (size < sizes[0] + sizes[1] + sizes[2])
- goto buffer_too_small;
-
- /* set caps */
- outcaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
- gst_pad_set_caps (ogg->srcpad, outcaps);
-
- /* copy header data */
- offs = 34;
- for (i = 0; i < 3; i++) {
- GstBuffer *out;
-
- /* now output the raw vorbis header packets */
- out = gst_buffer_create_sub (buffer, offs, sizes[i]);
- gst_buffer_set_caps (out, outcaps);
- gst_pad_push (ogg->srcpad, out);
-
- offs += sizes[i];
- }
- gst_caps_unref (outcaps);
-
- return TRUE;
-
- /* ERRORS */
-no_data:
- {
- GST_DEBUG_OBJECT (ogg, "no codec_data found in caps");
- return FALSE;
- }
-wrong_format:
- {
- GST_DEBUG_OBJECT (ogg, "codec_data is not a buffer");
- return FALSE;
- }
-buffer_too_small:
- {
- GST_DEBUG_OBJECT (ogg, "codec_data is too small");
- return FALSE;
- }
-}
-
-static gboolean
-gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event)
-{
- GstOggAviParse *ogg;
- gboolean ret;
-
- ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- ret = gst_pad_push_event (ogg->srcpad, event);
- break;
- case GST_EVENT_FLUSH_STOP:
- ogg_sync_reset (&ogg->sync);
- ogg_stream_reset (&ogg->stream);
- ogg->discont = TRUE;
- ret = gst_pad_push_event (ogg->srcpad, event);
- break;
- default:
- ret = gst_pad_push_event (ogg->srcpad, event);
- break;
- }
- return ret;
-}
-
-static GstFlowReturn
-gst_ogg_avi_parse_push_packet (GstOggAviParse * ogg, ogg_packet * packet)
-{
- GstBuffer *buffer;
- GstFlowReturn result;
-
- /* allocate space for header and body */
- buffer = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (GST_BUFFER_DATA (buffer), packet->packet, packet->bytes);
-
- GST_LOG_OBJECT (ogg, "created buffer %p from page", buffer);
-
- GST_BUFFER_OFFSET_END (buffer) = packet->granulepos;
-
- if (ogg->discont) {
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- ogg->discont = FALSE;
- }
-
- result = gst_pad_push (ogg->srcpad, buffer);
-
- return result;
-}
-
-static GstFlowReturn
-gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstFlowReturn result = GST_FLOW_OK;
- GstOggAviParse *ogg;
- guint8 *data;
- guint size;
- gchar *oggbuf;
- gint ret = -1;
-
- ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));
-
- data = GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer);
-
- GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size);
-
- if (GST_BUFFER_IS_DISCONT (buffer)) {
- ogg_sync_reset (&ogg->sync);
- ogg->discont = TRUE;
- }
-
- /* write data to sync layer */
- oggbuf = ogg_sync_buffer (&ogg->sync, size);
- memcpy (oggbuf, data, size);
- ogg_sync_wrote (&ogg->sync, size);
- gst_buffer_unref (buffer);
-
- /* try to get as many packets out of the stream as possible */
- do {
- ogg_page page;
-
- /* try to swap out a page */
- ret = ogg_sync_pageout (&ogg->sync, &page);
- if (ret == 0) {
- GST_DEBUG_OBJECT (ogg, "need more data");
- break;
- } else if (ret == -1) {
- GST_DEBUG_OBJECT (ogg, "discont in pages");
- ogg->discont = TRUE;
- } else {
- /* new unknown stream, init the ogg stream with the serial number of the
- * page. */
- if (ogg->serial == -1) {
- ogg->serial = ogg_page_serialno (&page);
- ogg_stream_init (&ogg->stream, ogg->serial);
- }
-
- /* submit page */
- if (ogg_stream_pagein (&ogg->stream, &page) != 0) {
- GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream");
- ogg_sync_reset (&ogg->sync);
- ogg->discont = TRUE;
- continue;
- }
-
- /* try to get as many packets as possible out of the page */
- do {
- ogg_packet packet;
-
- ret = ogg_stream_packetout (&ogg->stream, &packet);
- GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
- switch (ret) {
- case 0:
- break;
- case -1:
- /* out of sync, We mark a DISCONT. */
- ogg->discont = TRUE;
- break;
- case 1:
- result = gst_ogg_avi_parse_push_packet (ogg, &packet);
- if (GST_FLOW_IS_FATAL (result))
- goto done;
- break;
- default:
- GST_WARNING_OBJECT (ogg,
- "invalid return value %d for ogg_stream_packetout, resetting stream",
- ret);
- break;
- }
- }
- while (ret != 0);
- }
- }
- while (ret != 0);
-
-done:
- return result;
-}
-
-static GstStateChangeReturn
-gst_ogg_avi_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstOggAviParse *ogg;
- GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
- ogg = GST_OGG_AVI_PARSE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- ogg_sync_init (&ogg->sync);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- ogg_sync_reset (&ogg->sync);
- ogg_stream_reset (&ogg->stream);
- ogg->serial = -1;
- ogg->discont = TRUE;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- result = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- ogg_sync_clear (&ogg->sync);
- break;
- default:
- break;
- }
- return result;
-}
-
-gboolean
-gst_ogg_avi_parse_plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_ogg_avi_parse_debug, "oggaviparse", 0,
- "ogg avi parser");
-
- return gst_element_register (plugin, "oggaviparse", GST_RANK_PRIMARY,
- GST_TYPE_OGG_AVI_PARSE);
-}
--- a/gst_plugins_base/ext/ogg/gstoggdemux.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3323 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- *
- * gstoggdemux.c: ogg stream demuxer
- *
- * 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.
- */
-
-/**
- * SECTION:element-oggdemux
- * @short_description: a demuxer for ogg files
- *
- * <refsect2>
- * <para>
- * This element demuxes ogg files into their encoded audio and video components.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=test.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
- * </programlisting>
- * Decodes the vorbis audio stored inside an ogg container.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-12-30 (0.10.5)
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <string.h>
-#include <gst/gst-i18n-plugin.h>
-#include <gst/base/gsttypefindhelper.h>
-
-#include "gstoggdemux.h"
-
-static const GstElementDetails gst_ogg_demux_details =
-GST_ELEMENT_DETAILS ("Ogg demuxer",
- "Codec/Demuxer",
- "demux ogg streams (info about ogg: http://xiph.org)",
- "Wim Taymans <wim@fluendo.com>");
-
-#define CHUNKSIZE (8500) /* this is out of vorbisfile */
-#define SKELETON_FISHEAD_SIZE 64
-#define SKELETON_FISBONE_MIN_SIZE 52
-
-#define GST_FLOW_LIMIT GST_FLOW_CUSTOM_ERROR
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_debug);
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_demux_setup_debug);
-#define GST_CAT_DEFAULT gst_ogg_demux_debug
-
-static ogg_page *
-gst_ogg_page_copy (ogg_page * page)
-{
- ogg_page *p = g_new0 (ogg_page, 1);
-
- /* make a copy of the page */
- p->header = g_memdup (page->header, page->header_len);
- p->header_len = page->header_len;
- p->body = g_memdup (page->body, page->body_len);
- p->body_len = page->body_len;
-
- return p;
-}
-
-static void
-gst_ogg_page_free (ogg_page * page)
-{
- g_free (page->header);
- g_free (page->body);
- g_free (page);
-}
-
-static GstStaticPadTemplate internaltemplate =
-GST_STATIC_PAD_TEMPLATE ("internal",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static gboolean gst_ogg_demux_collect_chain_info (GstOggDemux * ogg,
- GstOggChain * chain);
-static gboolean gst_ogg_demux_activate_chain (GstOggDemux * ogg,
- GstOggChain * chain, GstEvent * event);
-static void gst_ogg_chain_mark_discont (GstOggChain * chain);
-
-static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg,
- GstEvent * event);
-static gboolean gst_ogg_demux_receive_event (GstElement * element,
- GstEvent * event);
-
-static void gst_ogg_pad_class_init (GstOggPadClass * klass);
-static void gst_ogg_pad_init (GstOggPad * pad);
-static void gst_ogg_pad_dispose (GObject * object);
-static void gst_ogg_pad_finalize (GObject * object);
-
-#if 0
-static const GstFormat *gst_ogg_pad_formats (GstPad * pad);
-static const GstEventMask *gst_ogg_pad_event_masks (GstPad * pad);
-#endif
-static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad);
-static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query);
-static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
-static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
- glong serialno);
-
-static gboolean gst_ogg_pad_query_convert (GstOggPad * pad,
- GstFormat src_format, gint64 src_val,
- GstFormat * dest_format, gint64 * dest_val);
-static GstClockTime gst_annodex_granule_to_time (gint64 granulepos,
- gint64 granulerate_n, gint64 granulerate_d, guint8 granuleshift);
-
-static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg,
- GstOggPad * pad, GstFlowReturn ret);
-
-static GstPadClass *ogg_pad_parent_class = NULL;
-
-static GType
-gst_ogg_pad_get_type (void)
-{
- static GType ogg_pad_type = 0;
-
- if (!ogg_pad_type) {
- static const GTypeInfo ogg_pad_info = {
- sizeof (GstOggPadClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_ogg_pad_class_init,
- NULL,
- NULL,
- sizeof (GstOggPad),
- 0,
- (GInstanceInitFunc) gst_ogg_pad_init,
- };
-
- ogg_pad_type =
- g_type_register_static (GST_TYPE_PAD, "GstOggPad", &ogg_pad_info, 0);
- }
- return ogg_pad_type;
-}
-
-static void
-gst_ogg_pad_class_init (GstOggPadClass * klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = (GObjectClass *) klass;
-
- ogg_pad_parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->dispose = gst_ogg_pad_dispose;
- gobject_class->finalize = gst_ogg_pad_finalize;
-}
-
-static void
-gst_ogg_pad_init (GstOggPad * pad)
-{
- gst_pad_set_event_function (GST_PAD (pad),
- GST_DEBUG_FUNCPTR (gst_ogg_pad_event));
- gst_pad_set_getcaps_function (GST_PAD (pad),
- GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps));
- gst_pad_set_query_type_function (GST_PAD (pad),
- GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types));
- gst_pad_set_query_function (GST_PAD (pad),
- GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query));
-
- pad->mode = GST_OGG_PAD_MODE_INIT;
-
- pad->first_granule = -1;
- pad->current_granule = -1;
-
- pad->start_time = GST_CLOCK_TIME_NONE;
- pad->first_time = GST_CLOCK_TIME_NONE;
-
- pad->have_type = FALSE;
- pad->continued = NULL;
- pad->headers = NULL;
-}
-
-static void
-gst_ogg_pad_dispose (GObject * object)
-{
- GstOggPad *pad = GST_OGG_PAD (object);
- GstPad **elem_pad_p;
- GstElement **element_p;
- GstPad **elem_out_p;
-
- if (pad->element)
- gst_element_set_state (pad->element, GST_STATE_NULL);
-
- elem_pad_p = &pad->elem_pad;
- element_p = &pad->element;
- elem_out_p = &pad->elem_out;
- gst_object_replace ((GstObject **) elem_pad_p, NULL);
- gst_object_replace ((GstObject **) element_p, NULL);
- gst_object_replace ((GstObject **) elem_out_p, NULL);
-
- pad->chain = NULL;
- pad->ogg = NULL;
-
- g_list_foreach (pad->headers, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (pad->headers);
- pad->headers = NULL;
-
- /* clear continued pages */
- g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
- g_list_free (pad->continued);
- pad->continued = NULL;
-
- ogg_stream_reset (&pad->stream);
-
- G_OBJECT_CLASS (ogg_pad_parent_class)->dispose (object);
-}
-
-static void
-gst_ogg_pad_finalize (GObject * object)
-{
- GstOggPad *pad = GST_OGG_PAD (object);
-
- ogg_stream_clear (&pad->stream);
-
- G_OBJECT_CLASS (ogg_pad_parent_class)->finalize (object);
-}
-
-#if 0
-static const GstFormat *
-gst_ogg_pad_formats (GstPad * pad)
-{
- static GstFormat src_formats[] = {
- GST_FORMAT_DEFAULT, /* time */
- GST_FORMAT_TIME, /* granulepos */
- 0
- };
- static GstFormat sink_formats[] = {
- GST_FORMAT_BYTES,
- GST_FORMAT_DEFAULT, /* bytes */
- 0
- };
-
- return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
-}
-#endif
-
-#if 0
-static const GstEventMask *
-gst_ogg_pad_event_masks (GstPad * pad)
-{
- static const GstEventMask src_event_masks[] = {
- {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
- {0,}
- };
-
- return src_event_masks;
-}
-#endif
-
-static const GstQueryType *
-gst_ogg_pad_query_types (GstPad * pad)
-{
- static const GstQueryType query_types[] = {
- GST_QUERY_DURATION,
- GST_QUERY_SEEKING,
- 0
- };
-
- return query_types;
-}
-
-static GstCaps *
-gst_ogg_pad_getcaps (GstPad * pad)
-{
- return gst_caps_ref (GST_PAD_CAPS (pad));
-}
-
-static gboolean
-gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
-{
- gboolean res = TRUE;
- GstOggDemux *ogg;
- GstOggPad *cur;
-
- ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
- cur = GST_OGG_PAD (pad);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_DURATION:
- {
- GstFormat format;
-
- gst_query_parse_duration (query, &format, NULL);
- /* can only get position in time */
- if (format != GST_FORMAT_TIME)
- goto wrong_format;
-
- /* can only return the total time position */
- /* FIXME, return time for this specific stream */
- gst_query_set_duration (query, GST_FORMAT_TIME, ogg->total_time);
- break;
- }
- case GST_QUERY_SEEKING:
- {
- GstFormat format;
-
- gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
- if (format == GST_FORMAT_TIME) {
- gst_query_set_seeking (query, GST_FORMAT_TIME, ogg->seekable,
- 0, ogg->total_time);
- } else {
- res = FALSE;
- }
- break;
- }
-
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-done:
- gst_object_unref (ogg);
-
- return res;
-
- /* ERRORS */
-wrong_format:
- {
- GST_DEBUG_OBJECT (ogg, "only query duration on TIME is supported");
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-gst_ogg_demux_receive_event (GstElement * element, GstEvent * event)
-{
- gboolean res;
- GstOggDemux *ogg;
-
- ogg = GST_OGG_DEMUX (element);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- /* can't seek if we are not seekable, FIXME could pass the
- * seek query upstream after converting it to bytes using
- * the average bitrate of the stream. */
- if (!ogg->seekable) {
- GST_DEBUG_OBJECT (ogg, "seek on non seekable stream");
- goto error;
- }
-
- /* now do the seek */
- res = gst_ogg_demux_perform_seek (ogg, event);
- gst_event_unref (event);
- break;
- default:
- GST_DEBUG_OBJECT (ogg, "We only handle seek events here");
- goto error;
- }
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (ogg, "error handling event");
- gst_event_unref (event);
- return FALSE;
- }
-}
-
-static gboolean
-gst_ogg_pad_event (GstPad * pad, GstEvent * event)
-{
- gboolean res;
- GstOggDemux *ogg;
- GstOggPad *cur;
-
- ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
- cur = GST_OGG_PAD (pad);
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- /* can't seek if we are not seekable, FIXME could pass the
- * seek query upstream after converting it to bytes using
- * the average bitrate of the stream. */
- if (!ogg->seekable) {
- GST_DEBUG_OBJECT (ogg, "seek on non seekable stream");
- goto error;
- }
-
- /* now do the seek */
- res = gst_ogg_demux_perform_seek (ogg, event);
- gst_event_unref (event);
- break;
- default:
- res = gst_pad_event_default (pad, event);
- break;
- }
-done:
- gst_object_unref (ogg);
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (ogg, "error handling event");
- gst_event_unref (event);
- res = FALSE;
- goto done;
- }
-}
-
-static void
-gst_ogg_pad_reset (GstOggPad * pad)
-{
- ogg_stream_reset (&pad->stream);
-
- /* clear continued pages */
- g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL);
- g_list_free (pad->continued);
- pad->continued = NULL;
-
- pad->last_ret = GST_FLOW_OK;
-}
-
-/* the filter function for selecting the elements we can use in
- * autoplugging */
-static gboolean
-gst_ogg_demux_factory_filter (GstPluginFeature * feature, GstCaps * caps)
-{
- guint rank;
- const gchar *klass;
-
- /* we only care about element factories */
- if (!GST_IS_ELEMENT_FACTORY (feature))
- return FALSE;
-
- klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
- /* only demuxers and decoders can play */
- if (strstr (klass, "Demux") == NULL &&
- strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL) {
- return FALSE;
- }
-
- /* only select elements with autoplugging rank */
- rank = gst_plugin_feature_get_rank (feature);
- if (rank < GST_RANK_MARGINAL)
- return FALSE;
-
- GST_DEBUG ("checking factory %s", GST_PLUGIN_FEATURE_NAME (feature));
- /* now see if it is compatible with the caps */
- {
- GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
- const GList *templates;
- GList *walk;
-
- /* get the templates from the element factory */
- templates = gst_element_factory_get_static_pad_templates (factory);
-
- for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
- GstStaticPadTemplate *templ = walk->data;
-
- /* we only care about the sink templates */
- if (templ->direction == GST_PAD_SINK) {
- GstCaps *intersect;
- GstCaps *scaps;
- gboolean empty;
-
- /* try to intersect the caps with the caps of the template */
- scaps = gst_static_caps_get (&templ->static_caps);
- intersect = gst_caps_intersect (caps, scaps);
- gst_caps_unref (scaps);
-
- empty = gst_caps_is_empty (intersect);
- gst_caps_unref (intersect);
-
- /* check if the intersection is empty */
- if (!empty) {
- /* non empty intersection, we can use this element */
- goto found;
- }
- }
- }
- }
- return FALSE;
-
-found:
- return TRUE;
-}
-
-/* function used to sort element features */
-static gint
-compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
-{
- gint diff;
-
- diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
- if (diff != 0)
- return diff;
- return strcmp (gst_plugin_feature_get_name (f2),
- gst_plugin_feature_get_name (f1));
-}
-
-/* called when the skeleton fishead is found. Caller ensures the packet is
- * precisely the correct size; we don't re-check this here. */
-static void
-gst_ogg_pad_parse_skeleton_fishead (GstOggPad * pad, ogg_packet * packet)
-{
- GstOggDemux *ogg = pad->ogg;
- guint8 *data = packet->packet;
- guint16 major, minor;
- gint64 prestime_n, prestime_d;
- gint64 basetime_n, basetime_d;
-
- /* skip "fishead\0" */
- data += 8;
- major = GST_READ_UINT16_LE (data);
- data += 2;
- minor = GST_READ_UINT16_LE (data);
- data += 2;
- prestime_n = (gint64) GST_READ_UINT64_LE (data);
- data += 8;
- prestime_d = (gint64) GST_READ_UINT64_LE (data);
- data += 8;
- basetime_n = (gint64) GST_READ_UINT64_LE (data);
- data += 8;
- basetime_d = (gint64) GST_READ_UINT64_LE (data);
- data += 8;
-
- ogg->basetime = gst_util_uint64_scale (GST_SECOND, basetime_n, basetime_d);
- ogg->have_fishead = TRUE;
- pad->is_skeleton = TRUE;
- pad->start_time = GST_CLOCK_TIME_NONE;
- pad->first_granule = -1;
- pad->first_time = GST_CLOCK_TIME_NONE;
- GST_INFO_OBJECT (ogg, "skeleton fishead parsed (basetime: %"
- GST_TIME_FORMAT ")", GST_TIME_ARGS (ogg->basetime));
-}
-
-/* function called when a skeleton fisbone is found. Caller ensures that
- * the packet length is sufficient */
-static void
-gst_ogg_pad_parse_skeleton_fisbone (GstOggPad * pad, ogg_packet * packet)
-{
- GstOggPad *fisbone_pad;
- gint64 start_granule;
- guint32 serialno;
- guint8 *data = packet->packet;
-
- /* skip "fisbone\0" */
- data += 8;
- /* skip headers offset */
- data += 4;
- serialno = GST_READ_UINT32_LE (data);
-
- fisbone_pad = gst_ogg_chain_get_stream (pad->chain, serialno);
- if (fisbone_pad) {
- if (fisbone_pad->have_fisbone)
- /* already parsed */
- return;
-
- fisbone_pad->have_fisbone = TRUE;
-
- data += 4;
- /* skip number of headers */
- data += 4;
- fisbone_pad->granulerate_n = GST_READ_UINT64_LE (data);
- data += 8;
- fisbone_pad->granulerate_d = GST_READ_UINT64_LE (data);
- data += 8;
- start_granule = GST_READ_UINT64_LE (data);
- data += 8;
- fisbone_pad->preroll = GST_READ_UINT32_LE (data);
- data += 4;
- fisbone_pad->granuleshift = GST_READ_UINT8 (data);
- data += 1;
- /* padding */
- data += 3;
-
- fisbone_pad->start_time = gst_annodex_granule_to_time (start_granule,
- fisbone_pad->granulerate_n, fisbone_pad->granulerate_d,
- fisbone_pad->granuleshift);
-
- GST_INFO_OBJECT (pad->ogg, "skeleton fisbone parsed "
- "(serialno: %08x start time: %" GST_TIME_FORMAT
- " granulerate_n: %" G_GINT64_FORMAT " granulerate_d: %" G_GINT64_FORMAT
- " preroll: %" G_GUINT32_FORMAT " granuleshift: %d)",
- serialno, GST_TIME_ARGS (fisbone_pad->start_time),
- fisbone_pad->granulerate_n, fisbone_pad->granulerate_d,
- fisbone_pad->preroll, fisbone_pad->granuleshift);
- } else {
- GST_WARNING_OBJECT (pad->ogg,
- "found skeleton fisbone for an unknown stream %" G_GUINT32_FORMAT,
- serialno);
- }
-}
-
-/* function called to convert a granulepos to a timestamp */
-static gboolean
-gst_ogg_pad_query_convert (GstOggPad * pad, GstFormat src_format,
- gint64 src_val, GstFormat * dest_format, gint64 * dest_val)
-{
- gboolean res;
-
- if (src_val == -1) {
- *dest_val = -1;
- return TRUE;
- }
-
- if (!pad->have_fisbone && pad->elem_pad == NULL)
- return FALSE;
-
- switch (src_format) {
- case GST_FORMAT_DEFAULT:
- if (pad->have_fisbone && *dest_format == GST_FORMAT_TIME) {
- *dest_val = gst_annodex_granule_to_time (src_val,
- pad->granulerate_n, pad->granulerate_d, pad->granuleshift);
-
- res = TRUE;
- } else {
- if (pad->elem_pad == NULL)
- res = FALSE;
- else
- res = gst_pad_query_convert (pad->elem_pad, src_format, src_val,
- dest_format, dest_val);
- }
-
- break;
- default:
- if (pad->elem_pad == NULL)
- res = FALSE;
- else
- res = gst_pad_query_convert (pad->elem_pad, src_format, src_val,
- dest_format, dest_val);
- }
-
- return res;
-}
-
-/* function called by the internal decoder elements when it outputs
- * a buffer. We use it to get the first timestamp of the stream
- */
-static GstFlowReturn
-gst_ogg_pad_internal_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstOggPad *oggpad;
- GstOggDemux *ogg;
- GstClockTime timestamp;
-
- oggpad = gst_pad_get_element_private (pad);
- ogg = GST_OGG_DEMUX (oggpad->ogg);
-
- timestamp = GST_BUFFER_TIMESTAMP (buffer);
- GST_DEBUG_OBJECT (oggpad, "received buffer from internal pad, TS=%"
- GST_TIME_FORMAT "=%" G_GINT64_FORMAT, GST_TIME_ARGS (timestamp),
- timestamp);
-
- if (oggpad->start_time == GST_CLOCK_TIME_NONE) {
- oggpad->start_time = timestamp;
- GST_DEBUG_OBJECT (oggpad, "new start time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (timestamp));
- }
-
- gst_buffer_unref (buffer);
-
- return GST_FLOW_OK;
-}
-
-static void
-internal_element_pad_added_cb (GstElement * element, GstPad * pad,
- GstOggPad * oggpad)
-{
- if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
- if (!(gst_pad_link (pad, oggpad->elem_out) == GST_PAD_LINK_OK)) {
- GST_ERROR ("Really couldn't find a valid pad");
- }
- oggpad->dynamic = FALSE;
- g_signal_handler_disconnect (element, oggpad->padaddedid);
- oggpad->padaddedid = 0;
- }
-}
-
-/* runs typefind on the packet, which is assumed to be the first
- * packet in the stream.
- *
- * Based on the type returned from the typefind function, an element
- * is created to help in conversion between granulepos and timestamps
- * so that we can do decent seeking.
- */
-static gboolean
-gst_ogg_pad_typefind (GstOggPad * pad, ogg_packet * packet)
-{
- GstBuffer *buf;
- GstCaps *caps;
- GstElement *element = NULL;
-
-#ifndef GST_DISABLE_GST_DEBUG
- GstOggDemux *ogg = pad->ogg;
-#endif
-
- if (GST_PAD_CAPS (pad) != NULL)
- return TRUE;
-
- /* The ogg spec defines that the first packet of an ogg stream must identify
- * the stream. Therefore ogg can use a simplified approach to typefinding
- * and only needs to check the first packet */
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = packet->packet;
- GST_BUFFER_SIZE (buf) = packet->bytes;
- GST_BUFFER_OFFSET (buf) = 0;
-
- caps = gst_type_find_helper_for_buffer (GST_OBJECT (pad), buf, NULL);
- gst_buffer_unref (buf);
-
- if (caps == NULL) {
- GST_WARNING_OBJECT (ogg,
- "couldn't find caps for stream with serial %08x", pad->serialno);
- caps = gst_caps_new_simple ("application/octet-stream", NULL);
- } else {
- /* ogg requires you to use a decoder element to define the
- * meaning of granulepos etc so we make one. We also do this if
- * we are in the streaming mode to calculate the first timestamp. */
- GList *factories;
-
- GST_LOG_OBJECT (ogg, "found caps: %" GST_PTR_FORMAT, caps);
-
- /* first filter out the interesting element factories */
- factories = gst_default_registry_feature_filter (
- (GstPluginFeatureFilter) gst_ogg_demux_factory_filter, FALSE, caps);
-
- /* sort them according to their ranks */
- factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
-
- /* then pick the first factory to create an element */
- if (factories) {
- element =
- gst_element_factory_create (GST_ELEMENT_FACTORY (factories->data),
- NULL);
- if (element) {
- GstPadTemplate *template;
-
- /* this is ours */
- gst_object_ref (element);
- gst_object_sink (GST_OBJECT (element));
-
- /* FIXME, it might not be named "sink" */
- pad->elem_pad = gst_element_get_pad (element, "sink");
- gst_element_set_state (element, GST_STATE_PAUSED);
- template = gst_static_pad_template_get (&internaltemplate);
- pad->elem_out = gst_pad_new_from_template (template, "internal");
- gst_pad_set_chain_function (pad->elem_out, gst_ogg_pad_internal_chain);
- gst_pad_set_element_private (pad->elem_out, pad);
- gst_pad_set_active (pad->elem_out, TRUE);
- gst_object_unref (template);
-
- /* and this pad may not be named src.. */
- /* And it might also not exist at this time... */
- {
- GstPad *p;
-
- p = gst_element_get_pad (element, "src");
- if (p) {
- gst_pad_link (p, pad->elem_out);
- gst_object_unref (p);
- } else {
- pad->dynamic = TRUE;
- pad->padaddedid = g_signal_connect (G_OBJECT (element),
- "pad-added", G_CALLBACK (internal_element_pad_added_cb), pad);
- }
- }
- }
- }
- g_list_free (factories);
- }
- pad->element = element;
-
- gst_pad_set_caps (GST_PAD (pad), caps);
- gst_caps_unref (caps);
-
- return TRUE;
-}
-
-/* send packet to internal element */
-static GstFlowReturn
-gst_ogg_demux_chain_elem_pad (GstOggPad * pad, ogg_packet * packet)
-{
- GstBuffer *buf;
- GstFlowReturn ret;
-
-#ifndef GST_DISABLE_GST_DEBUG
- GstOggDemux *ogg = pad->ogg;
-#endif
-
- /* initialize our internal decoder with packets */
- if (!pad->elem_pad)
- goto no_decoder;
-
- GST_DEBUG_OBJECT (ogg, "%p init decoder serial %08x", pad, pad->serialno);
-
- buf = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
- GST_BUFFER_OFFSET (buf) = -1;
- GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
-
- ret = gst_pad_chain (pad->elem_pad, buf);
- if (GST_FLOW_IS_FATAL (ret))
- goto decoder_error;
-
- return ret;
-
-no_decoder:
- {
- GST_WARNING_OBJECT (ogg,
- "pad %p does not have elem_pad, no decoder ?", pad);
- return GST_FLOW_ERROR;
- }
-decoder_error:
- {
- GST_WARNING_OBJECT (ogg, "internal decoder error");
- return GST_FLOW_ERROR;
- }
-}
-
-/* queue data, basically takes the packet, puts it in a buffer and store the
- * buffer in the headers list.
- */
-static GstFlowReturn
-gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet)
-{
- GstBuffer *buf;
-
-#ifndef GST_DISABLE_GST_DEBUG
- GstOggDemux *ogg = pad->ogg;
-#endif
-
- GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08x", pad, pad->serialno);
-
- buf = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (buf->data, packet->packet, packet->bytes);
- GST_BUFFER_OFFSET (buf) = -1;
- GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
- pad->headers = g_list_append (pad->headers, buf);
-
- /* we are ok now */
- return GST_FLOW_OK;
-}
-
-/* send packet to internal element */
-static GstFlowReturn
-gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet)
-{
- GstBuffer *buf;
- GstFlowReturn ret, cret;
- GstOggDemux *ogg = pad->ogg;
- GstFormat format;
- gint64 current_time;
- GstOggChain *chain;
-
- GST_DEBUG_OBJECT (ogg,
- "%p streaming to peer serial %08x", pad, pad->serialno);
-
- ret =
- gst_pad_alloc_buffer_and_set_caps (GST_PAD_CAST (pad),
- GST_BUFFER_OFFSET_NONE, packet->bytes, GST_PAD_CAPS (pad), &buf);
-
- /* combine flows */
- cret = gst_ogg_demux_combine_flows (ogg, pad, ret);
- if (ret != GST_FLOW_OK)
- goto no_buffer;
-
- /* copy packet in buffer */
- memcpy (buf->data, packet->packet, packet->bytes);
-
- GST_BUFFER_OFFSET (buf) = -1;
- GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
-
- /* Mark discont on the buffer */
- if (pad->discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- pad->discont = FALSE;
- }
-
- ret = gst_pad_push (GST_PAD_CAST (pad), buf);
-
- /* combine flows */
- cret = gst_ogg_demux_combine_flows (ogg, pad, ret);
-
- /* we're done with skeleton stuff */
- if (pad->is_skeleton)
- goto done;
-
- /* check if valid granulepos, then we can calculate the current
- * position */
- if (packet->granulepos < 0)
- goto done;
-
- /* store current granule pos */
- ogg->current_granule = packet->granulepos;
-
- /* convert to time */
- format = GST_FORMAT_TIME;
- if (!gst_ogg_pad_query_convert (pad,
- GST_FORMAT_DEFAULT, packet->granulepos, &format,
- (gint64 *) & current_time))
- goto convert_failed;
-
- /* convert to stream time */
- if ((chain = pad->chain))
- current_time = current_time - chain->segment_start + chain->begin_time;
-
- /* and store as the current position */
- gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time);
-
- GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (current_time));
-
-done:
- /* return combined flow result */
- return cret;
-
- /* special cases */
-no_buffer:
- {
- GST_DEBUG_OBJECT (ogg,
- "%p could not get buffer from peer %08x, %d (%s), combined %d (%s)",
- pad, pad->serialno, ret, gst_flow_get_name (ret),
- cret, gst_flow_get_name (cret));
- goto done;
- }
-convert_failed:
- {
- GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
- goto done;
- }
-}
-
-/* submit a packet to the oggpad, this function will run the
- * typefind code for the pad if this is the first packet for this
- * stream
- */
-static GstFlowReturn
-gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
-{
- gint64 granule;
- GstFlowReturn ret;
-
- GstOggDemux *ogg = pad->ogg;
-
- GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08x", pad, pad->serialno);
-
- if (!pad->have_type) {
- if (!ogg->have_fishead && packet->bytes == SKELETON_FISHEAD_SIZE &&
- !memcmp (packet->packet, "fishead\0", 8)) {
- gst_ogg_pad_parse_skeleton_fishead (pad, packet);
- }
- gst_ogg_pad_typefind (pad, packet);
- pad->have_type = TRUE;
- }
-
- if (ogg->have_fishead && packet->bytes >= SKELETON_FISBONE_MIN_SIZE &&
- !memcmp (packet->packet, "fisbone\0", 8)) {
- gst_ogg_pad_parse_skeleton_fisbone (pad, packet);
- }
-
- granule = packet->granulepos;
- if (granule != -1) {
- GST_DEBUG_OBJECT (ogg, "%p has granulepos %" G_GINT64_FORMAT, pad, granule);
- ogg->current_granule = granule;
- pad->current_granule = granule;
- /* granulepos 0 and -1 are considered header packets.
- * Note that since theora is busted, it can create non-header
- * packets with 0 granulepos. We will correct for this when our
- * internal decoder produced a frame and we don't have a
- * granulepos because in that case the granulpos must have been 0 */
- if (pad->first_granule == -1 && granule != 0) {
- GST_DEBUG_OBJECT (ogg, "%p found first granulepos %" G_GINT64_FORMAT, pad,
- granule);
- pad->first_granule = granule;
- }
- }
-
- if (granule != -1 && memcmp (packet->packet, "KW-DIRAC", 8) == 0) {
- return GST_FLOW_OK;
- }
-
- /* no start time known, stream to internal plugin to
- * get time. always stream to the skeleton decoder */
- if (pad->start_time == GST_CLOCK_TIME_NONE || pad->is_skeleton) {
- ret = gst_ogg_demux_chain_elem_pad (pad, packet);
- }
- /* we know the start_time of the pad data, see if we
- * can activate the complete chain if this is a dynamic
- * chain. */
- if (pad->start_time != GST_CLOCK_TIME_NONE) {
- GstOggChain *chain = pad->chain;
-
- /* correction for busted ogg, if the internal decoder outputed
- * a timestamp but we did not get a granulepos, it must have
- * been 0 and the time is therefore also 0 */
- if (pad->first_granule == -1) {
- GST_DEBUG_OBJECT (ogg, "%p found start time without granulepos", pad);
- pad->first_granule = 0;
- pad->first_time = 0;
- }
-
- /* check if complete chain has start time */
- if (chain == ogg->building_chain) {
-
- /* see if we have enough info to activate the chain, we have enough info
- * when all streams have a valid start time. */
- if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
- GstEvent *event;
-
- GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->segment_start));
- GST_DEBUG_OBJECT (ogg, "segment_stop: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->segment_stop));
- GST_DEBUG_OBJECT (ogg, "segment_time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->begin_time));
-
- /* create the newsegment event we are going to send out */
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
- chain->begin_time);
-
- gst_ogg_demux_activate_chain (ogg, chain, event);
-
- ogg->building_chain = NULL;
- }
- }
- }
-
- /* if we are building a chain, store buffer for when we activate
- * it. This path is taken if we operate in streaming mode. */
- if (ogg->building_chain) {
- ret = gst_ogg_demux_queue_data (pad, packet);
- }
- /* else we are completely streaming to the peer */
- else {
- ret = gst_ogg_demux_chain_peer (pad, packet);
- }
- return ret;
-}
-
-/* flush at most @npackets from the stream layer. All packets if
- * @npackets is 0;
- */
-static GstFlowReturn
-gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets)
-{
- GstFlowReturn result = GST_FLOW_OK;
- gboolean done = FALSE;
- GstOggDemux *ogg;
-
- ogg = pad->ogg;
-
- while (!done) {
- int ret;
- ogg_packet packet;
-
- ret = ogg_stream_packetout (&pad->stream, &packet);
- switch (ret) {
- case 0:
- GST_LOG_OBJECT (ogg, "packetout done");
- done = TRUE;
- break;
- case -1:
- GST_LOG_OBJECT (ogg, "packetout discont");
- gst_ogg_chain_mark_discont (pad->chain);
- break;
- case 1:
- GST_LOG_OBJECT (ogg, "packetout gave packet of size %ld", packet.bytes);
- result = gst_ogg_pad_submit_packet (pad, &packet);
- if (GST_FLOW_IS_FATAL (result))
- goto could_not_submit;
- break;
- default:
- GST_WARNING_OBJECT (ogg,
- "invalid return value %d for ogg_stream_packetout, resetting stream",
- ret);
- gst_ogg_pad_reset (pad);
- break;
- }
- if (npackets > 0) {
- npackets--;
- done = (npackets == 0);
- }
- }
- return result;
-
- /* ERRORS */
-could_not_submit:
- {
- GST_WARNING_OBJECT (ogg,
- "could not submit packet for stream %08x, error: %d", pad->serialno,
- result);
- gst_ogg_pad_reset (pad);
- return result;
- }
-}
-
-/* submit a page to an oggpad, this function will then submit all
- * the packets in the page.
- */
-static GstFlowReturn
-gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
-{
- GstFlowReturn result = GST_FLOW_OK;
- GstOggDemux *ogg;
- gboolean continued = FALSE;
-
- ogg = pad->ogg;
-
- /* for negative rates we read pages backwards and must therefore be carefull
- * with continued pages */
- if (ogg->segment.rate < 0.0) {
- gint npackets;
-
- continued = ogg_page_continued (page);
-
- /* number of completed packets in the page */
- npackets = ogg_page_packets (page);
- if (!continued) {
- /* page is not continued so it contains at least one packet start. It's
- * possible that no packet ends on this page (npackets == 0). In that
- * case, the next (continued) page(s) we kept contain the remainder of the
- * packets. We mark npackets=1 to make us start decoding the pages in the
- * remainder of the algorithm. */
- if (npackets == 0)
- npackets = 1;
- }
- GST_LOG_OBJECT (ogg, "continued: %d, %d packets", continued, npackets);
-
- if (npackets == 0) {
- GST_LOG_OBJECT (ogg, "no decodable packets, we need a previous page");
- goto done;
- }
- }
-
- if (ogg_stream_pagein (&pad->stream, page) != 0)
- goto choked;
-
- /* flush all packets in the stream layer, this might not give a packet if
- * the page had no packets finishing on the page (npackets == 0). */
- result = gst_ogg_pad_stream_out (pad, 0);
-
- if (pad->continued) {
- ogg_packet packet;
-
- /* now send the continued pages to the stream layer */
- while (pad->continued) {
- ogg_page *p = (ogg_page *) pad->continued->data;
-
- GST_LOG_OBJECT (ogg, "submitting continued page %p", p);
- if (ogg_stream_pagein (&pad->stream, p) != 0)
- goto choked;
-
- pad->continued = g_list_delete_link (pad->continued, pad->continued);
-
- /* free the page */
- gst_ogg_page_free (p);
- }
-
- GST_LOG_OBJECT (ogg, "flushing last continued packet");
- /* flush 1 continued packet in the stream layer */
- result = gst_ogg_pad_stream_out (pad, 1);
-
- /* flush all remaining packets, we pushed them in the previous round.
- * We don't use _reset() because we still want to get the discont when
- * we submit a next page. */
- while (ogg_stream_packetout (&pad->stream, &packet) != 0);
- }
-
-done:
- /* keep continued pages (only in reverse mode) */
- if (continued) {
- ogg_page *p = gst_ogg_page_copy (page);
-
- GST_LOG_OBJECT (ogg, "keeping continued page %p", p);
- pad->continued = g_list_prepend (pad->continued, p);
- }
-
- return result;
-
-choked:
- {
- GST_WARNING_OBJECT (ogg,
- "ogg stream choked on page (serial %08x), resetting stream",
- pad->serialno);
- gst_ogg_pad_reset (pad);
- /* we continue to recover */
- return GST_FLOW_OK;
- }
-}
-
-
-static GstOggChain *
-gst_ogg_chain_new (GstOggDemux * ogg)
-{
- GstOggChain *chain = g_new0 (GstOggChain, 1);
-
- GST_DEBUG_OBJECT (ogg, "creating new chain %p", chain);
- chain->ogg = ogg;
- chain->offset = -1;
- chain->bytes = -1;
- chain->have_bos = FALSE;
- chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *));
- chain->begin_time = GST_CLOCK_TIME_NONE;
- chain->segment_start = GST_CLOCK_TIME_NONE;
- chain->segment_stop = GST_CLOCK_TIME_NONE;
- chain->total_time = GST_CLOCK_TIME_NONE;
-
- return chain;
-}
-
-static void
-gst_ogg_chain_free (GstOggChain * chain)
-{
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- gst_object_unref (pad);
- }
- g_array_free (chain->streams, TRUE);
- g_free (chain);
-}
-
-static void
-gst_ogg_chain_mark_discont (GstOggChain * chain)
-{
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- pad->discont = TRUE;
- }
-}
-
-static void
-gst_ogg_chain_reset (GstOggChain * chain)
-{
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- gst_ogg_pad_reset (pad);
- }
-}
-
-static GstOggPad *
-gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno)
-{
- GstOggPad *ret;
- GstTagList *list;
- gchar *name;
-
- GST_DEBUG_OBJECT (chain->ogg, "creating new stream %08lx in chain %p",
- serialno, chain);
-
- ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
- /* we own this one */
- gst_object_ref (ret);
- gst_object_sink (ret);
-
- GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
- ret->discont = TRUE;
-
- ret->chain = chain;
- ret->ogg = chain->ogg;
-
- ret->serialno = serialno;
- if (ogg_stream_init (&ret->stream, serialno) != 0)
- goto init_failed;
-
- name = g_strdup_printf ("serial_%08lx", serialno);
- gst_object_set_name (GST_OBJECT (ret), name);
- g_free (name);
-
- /* FIXME: either do something with it or remove it */
- list = gst_tag_list_new ();
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serialno,
- NULL);
- gst_tag_list_free (list);
-
- GST_DEBUG_OBJECT (chain->ogg,
- "created new ogg src %p for stream with serial %08lx", ret, serialno);
-
- g_array_append_val (chain->streams, ret);
-
- return ret;
-
- /* ERRORS */
-init_failed:
- {
- GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.",
- serialno);
- gst_object_unref (ret);
- return NULL;
- }
-}
-
-static GstOggPad *
-gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno)
-{
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- if (pad->serialno == serialno)
- return pad;
- }
- return NULL;
-}
-
-static gboolean
-gst_ogg_chain_has_stream (GstOggChain * chain, glong serialno)
-{
- return gst_ogg_chain_get_stream (chain, serialno) != NULL;
-}
-
-#define CURRENT_CHAIN(ogg) (&g_array_index ((ogg)->chains, GstOggChain, (ogg)->current_chain))
-
-/* signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0
- /* FILL ME */
-};
-
-static GstStaticPadTemplate ogg_demux_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src_%d",
- GST_PAD_SRC,
- GST_PAD_SOMETIMES,
- GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate ogg_demux_sink_template_factory =
- GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/ogg; application/x-annodex")
- );
-
-static void gst_ogg_demux_finalize (GObject * object);
-
-//static const GstEventMask *gst_ogg_demux_get_event_masks (GstPad * pad);
-//static const GstQueryType *gst_ogg_demux_get_query_types (GstPad * pad);
-static GstFlowReturn gst_ogg_demux_read_chain (GstOggDemux * ogg,
- GstOggChain ** chain);
-static GstFlowReturn gst_ogg_demux_read_end_chain (GstOggDemux * ogg,
- GstOggChain * chain);
-
-static gboolean gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event);
-static void gst_ogg_demux_loop (GstOggPad * pad);
-static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_ogg_demux_sink_activate (GstPad * sinkpad);
-static gboolean gst_ogg_demux_sink_activate_pull (GstPad * sinkpad,
- gboolean active);
-static gboolean gst_ogg_demux_sink_activate_push (GstPad * sinkpad,
- gboolean active);
-static GstStateChangeReturn gst_ogg_demux_change_state (GstElement * element,
- GstStateChange transition);
-static void gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event);
-
-static void gst_ogg_print (GstOggDemux * demux);
-
-GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT);
-
-static void
-gst_ogg_demux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_ogg_demux_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_demux_sink_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_demux_src_template_factory));
-}
-static void
-gst_ogg_demux_class_init (GstOggDemuxClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gstelement_class->change_state = gst_ogg_demux_change_state;
- gstelement_class->send_event = gst_ogg_demux_receive_event;
-
- gobject_class->finalize = gst_ogg_demux_finalize;
-}
-
-static void
-gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class)
-{
- /* create the sink pad */
- ogg->sinkpad =
- gst_pad_new_from_static_template (&ogg_demux_sink_template_factory,
- "sink");
-
- gst_pad_set_event_function (ogg->sinkpad, gst_ogg_demux_sink_event);
- gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_demux_chain);
- gst_pad_set_activate_function (ogg->sinkpad, gst_ogg_demux_sink_activate);
- gst_pad_set_activatepull_function (ogg->sinkpad,
- gst_ogg_demux_sink_activate_pull);
- gst_pad_set_activatepush_function (ogg->sinkpad,
- gst_ogg_demux_sink_activate_push);
- gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
-
- ogg->chain_lock = g_mutex_new ();
- ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
-
- ogg->newsegment = NULL;
-}
-
-static void
-gst_ogg_demux_finalize (GObject * object)
-{
- GstOggDemux *ogg;
-
- ogg = GST_OGG_DEMUX (object);
-
- g_array_free (ogg->chains, TRUE);
- g_mutex_free (ogg->chain_lock);
- ogg_sync_clear (&ogg->sync);
-
- if (ogg->newsegment)
- gst_event_unref (ogg->newsegment);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static gboolean
-gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean res;
- GstOggDemux *ogg;
-
- ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:
- /* FIXME */
- GST_DEBUG_OBJECT (ogg, "got a new segment event");
- ogg_sync_reset (&ogg->sync);
- gst_event_unref (event);
- res = TRUE;
- break;
- case GST_EVENT_EOS:
- default:
- res = gst_pad_event_default (pad, event);
- break;
- }
- gst_object_unref (ogg);
-
- return res;
-}
-
-/* submit the given buffer to the ogg sync.
- *
- * Returns the number of bytes submited.
- */
-static GstFlowReturn
-gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
-{
- gint size;
- guint8 *data;
- gchar *oggbuffer;
- GstFlowReturn ret = GST_FLOW_OK;
-
- size = GST_BUFFER_SIZE (buffer);
- data = GST_BUFFER_DATA (buffer);
-
- GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
- if (G_UNLIKELY (size == 0))
- goto done;
-
- oggbuffer = ogg_sync_buffer (&ogg->sync, size);
- if (G_UNLIKELY (oggbuffer == NULL))
- goto no_buffer;
-
- memcpy (oggbuffer, data, size);
- if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0))
- goto write_failed;
-
-done:
- gst_buffer_unref (buffer);
-
- return ret;
-
- /* ERRORS */
-no_buffer:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
- (NULL), ("failed to get ogg sync buffer"));
- ret = GST_FLOW_ERROR;
- goto done;
- }
-write_failed:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
- (NULL), ("failed to write %d bytes to the sync buffer", size));
- ret = GST_FLOW_ERROR;
- goto done;
- }
-}
-
-/* in random access mode this code updates the current read position
- * and resets the ogg sync buffer so that the next read will happen
- * from this new location.
- */
-static void
-gst_ogg_demux_seek (GstOggDemux * ogg, gint64 offset)
-{
- GST_LOG_OBJECT (ogg, "seeking to %" G_GINT64_FORMAT, offset);
-
- ogg->offset = offset;
- ogg_sync_reset (&ogg->sync);
-}
-
-/* read more data from the current offset and submit to
- * the ogg sync layer.
- */
-static GstFlowReturn
-gst_ogg_demux_get_data (GstOggDemux * ogg)
-{
- GstFlowReturn ret;
- GstBuffer *buffer;
-
- GST_LOG_OBJECT (ogg, "get data %" G_GINT64_FORMAT " %" G_GINT64_FORMAT,
- ogg->offset, ogg->length);
- if (ogg->offset == ogg->length)
- goto eos;
-
- ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
- if (ret != GST_FLOW_OK)
- goto error;
-
- ret = gst_ogg_demux_submit_buffer (ogg, buffer);
-
- return ret;
-
- /* ERROR */
-eos:
- {
- GST_LOG_OBJECT (ogg, "reached EOS");
- return GST_FLOW_UNEXPECTED;
- }
-error:
- {
- GST_WARNING_OBJECT (ogg, "got %d (%s) from pull range", ret,
- gst_flow_get_name (ret));
- return ret;
- }
-}
-
-/* Read the next page from the current offset.
- * boundary: number of bytes ahead we allow looking for;
- * -1 if no boundary
- *
- * @offset will contain the offset the next page starts at when this function
- * returns GST_FLOW_OK.
- *
- * GST_FLOW_UNEXPECTED is returned on EOS.
- *
- * GST_FLOW_LIMIT is returned when we did not find a page before the
- * boundary. If @boundary is -1, this is never returned.
- *
- * Any other error returned while retrieving data from the peer is returned as
- * is.
- */
-static GstFlowReturn
-gst_ogg_demux_get_next_page (GstOggDemux * ogg, ogg_page * og, gint64 boundary,
- gint64 * offset)
-{
- gint64 end_offset = 0;
- GstFlowReturn ret;
-
- GST_LOG_OBJECT (ogg,
- "get next page, current offset %" G_GINT64_FORMAT ", bytes boundary %"
- G_GINT64_FORMAT, ogg->offset, boundary);
-
- if (boundary > 0)
- end_offset = ogg->offset + boundary;
-
- while (TRUE) {
- glong more;
-
- if (boundary > 0 && ogg->offset >= end_offset)
- goto boundary_reached;
-
- more = ogg_sync_pageseek (&ogg->sync, og);
-
- GST_LOG_OBJECT (ogg, "pageseek gave %ld", more);
-
- if (more < 0) {
- /* skipped n bytes */
- GST_LOG_OBJECT (ogg, "skipped %ld bytes", more);
- ogg->offset -= more;
- } else if (more == 0) {
- /* we need more data */
- if (boundary == 0)
- goto boundary_reached;
-
- GST_LOG_OBJECT (ogg, "need more data");
- ret = gst_ogg_demux_get_data (ogg);
- if (ret != GST_FLOW_OK)
- break;
- } else {
- gint64 res_offset = ogg->offset;
-
- /* got a page. Return the offset at the page beginning,
- advance the internal offset past the page end */
- if (offset)
- *offset = res_offset;
- ret = GST_FLOW_OK;
-
- ogg->offset += more;
- /* need to reset as we do not keep track of the bytes we
- * sent to the sync layer */
- ogg_sync_reset (&ogg->sync);
-
- GST_LOG_OBJECT (ogg,
- "got page at %" G_GINT64_FORMAT ", serial %08x, end at %"
- G_GINT64_FORMAT ", granule %" G_GINT64_FORMAT, res_offset,
- ogg_page_serialno (og), ogg->offset, ogg_page_granulepos (og));
- break;
- }
- }
- GST_LOG_OBJECT (ogg, "returning %d", ret);
-
- return ret;
-
- /* ERRORS */
-boundary_reached:
- {
- GST_LOG_OBJECT (ogg,
- "offset %" G_GINT64_FORMAT " >= end_offset %" G_GINT64_FORMAT,
- ogg->offset, end_offset);
- return GST_FLOW_LIMIT;
- }
-}
-
-/* from the current offset, find the previous page, seeking backwards
- * until we find the page.
- */
-static GstFlowReturn
-gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset)
-{
- GstFlowReturn ret;
- gint64 begin = ogg->offset;
- gint64 end = begin;
- gint64 cur_offset = -1;
-
- while (cur_offset == -1) {
- begin -= CHUNKSIZE;
- if (begin < 0)
- begin = 0;
-
- /* seek CHUNKSIZE back */
- gst_ogg_demux_seek (ogg, begin);
-
- /* now continue reading until we run out of data, if we find a page
- * start, we save it. It might not be the final page as there could be
- * another page after this one. */
- while (ogg->offset < end) {
- gint64 new_offset;
-
- ret =
- gst_ogg_demux_get_next_page (ogg, og, end - ogg->offset, &new_offset);
- /* we hit the upper limit, offset contains the last page start */
- if (ret == GST_FLOW_LIMIT)
- break;
- /* something went wrong */
- if (ret == GST_FLOW_UNEXPECTED)
- new_offset = 0;
- else if (ret != GST_FLOW_OK)
- return ret;
-
- /* offset is next page start */
- cur_offset = new_offset;
- }
- }
-
- /* we have the offset. Actually snork and hold the page now */
- gst_ogg_demux_seek (ogg, cur_offset);
- ret = gst_ogg_demux_get_next_page (ogg, og, -1, NULL);
- if (ret != GST_FLOW_OK)
- /* this shouldn't be possible */
- return ret;
-
- if (offset)
- *offset = cur_offset;
-
- return ret;
-}
-
-static gboolean
-gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg)
-{
- gint i;
- GstOggChain *chain = ogg->current_chain;
-
- if (chain == NULL)
- return TRUE;
-
- GST_DEBUG_OBJECT (ogg, "deactivating chain %p", chain);
-
- /* send EOS on all the pads */
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- gst_pad_push_event (GST_PAD_CAST (pad), gst_event_new_eos ());
-
- GST_DEBUG_OBJECT (ogg, "removing pad %" GST_PTR_FORMAT, pad);
-
- /* deactivate first */
- gst_pad_set_active (GST_PAD_CAST (pad), FALSE);
-
- gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
- }
- /* if we cannot seek back to the chain, we can destroy the chain
- * completely */
- if (!ogg->seekable) {
- gst_ogg_chain_free (chain);
- }
- ogg->current_chain = NULL;
-
- return TRUE;
-}
-
-static gboolean
-gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
- GstEvent * event)
-{
- gint i;
-
- if (chain == ogg->current_chain) {
- if (event)
- gst_event_unref (event);
- return TRUE;
- }
-
- gst_ogg_demux_deactivate_current_chain (ogg);
-
- /* FIXME, should not be called with NULL */
- if (chain == NULL) {
- ogg->current_chain = chain;
- return TRUE;
- }
-
- GST_DEBUG_OBJECT (ogg, "activating chain %p", chain);
-
- /* first add the pads */
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad;
-
- pad = g_array_index (chain->streams, GstOggPad *, i);
- GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
-
- /* mark discont */
- pad->discont = TRUE;
- pad->last_ret = GST_FLOW_OK;
-
- /* activate first */
- gst_pad_set_active (GST_PAD_CAST (pad), TRUE);
-
- gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad));
- }
-
- gst_element_no_more_pads (GST_ELEMENT (ogg));
- ogg->current_chain = chain;
-
- /* FIXME, must be sent from the streaming thread */
- if (event)
- gst_ogg_demux_send_event (ogg, event);
-
- GST_DEBUG_OBJECT (ogg, "starting chain");
-
- /* then send out any queued buffers */
- for (i = 0; i < chain->streams->len; i++) {
- GList *headers;
- GstOggPad *pad;
-
- pad = g_array_index (chain->streams, GstOggPad *, i);
-
- for (headers = pad->headers; headers; headers = g_list_next (headers)) {
- GstBuffer *buffer = GST_BUFFER (headers->data);
-
- if (pad->discont) {
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- pad->discont = FALSE;
- }
-
- /* we don't care about the return value here */
- gst_pad_push (GST_PAD_CAST (pad), buffer);
- }
- /* and free the headers */
- g_list_free (pad->headers);
- pad->headers = NULL;
- }
- return TRUE;
-}
-
-/*
- * do seek to time @position, return FALSE or chain and TRUE
- */
-static gboolean
-gst_ogg_demux_do_seek (GstOggDemux * ogg, gint64 position, gboolean accurate,
- GstOggChain ** rchain)
-{
- GstOggChain *chain = NULL;
- gint64 begin, end;
- gint64 begintime, endtime;
- gint64 target;
- gint64 best;
- gint64 total;
- gint64 result = 0;
- GstFlowReturn ret;
- gint i;
-
- /* first find the chain to search in */
- total = ogg->total_time;
- if (ogg->chains->len == 0)
- goto no_chains;
-
- for (i = ogg->chains->len - 1; i >= 0; i--) {
- chain = g_array_index (ogg->chains, GstOggChain *, i);
- total -= chain->total_time;
- if (position >= total)
- break;
- }
-
- begin = chain->offset;
- end = chain->end_offset;
- begintime = chain->begin_time;
- endtime = chain->begin_time + chain->total_time;
- target = position - total + begintime;
- if (accurate) {
- /* FIXME, seek 4 seconds early to catch keyframes, better implement
- * keyframe detection. */
- target = target - (gint64) 4 *GST_SECOND;
- }
- target = MAX (target, 0);
- best = begin;
-
- GST_DEBUG_OBJECT (ogg,
- "seeking to %" GST_TIME_FORMAT " in chain %p",
- GST_TIME_ARGS (position), chain);
- GST_DEBUG_OBJECT (ogg,
- "chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, begin,
- end);
- GST_DEBUG_OBJECT (ogg,
- "chain begin time %" GST_TIME_FORMAT ", end time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (begintime), GST_TIME_ARGS (endtime));
- GST_DEBUG_OBJECT (ogg, "target %" GST_TIME_FORMAT, GST_TIME_ARGS (target));
-
- /* perform the seek */
- while (begin < end) {
- gint64 bisect;
-
- if ((end - begin < CHUNKSIZE) || (endtime == begintime)) {
- bisect = begin;
- } else {
- /* take a (pretty decent) guess, avoiding overflow */
- gint64 rate = (end - begin) * GST_MSECOND / (endtime - begintime);
-
- bisect = (target - begintime) / GST_MSECOND * rate + begin - CHUNKSIZE;
-
- if (bisect <= begin)
- bisect = begin;
- GST_DEBUG_OBJECT (ogg, "Initial guess: %" G_GINT64_FORMAT, bisect);
- }
- gst_ogg_demux_seek (ogg, bisect);
-
- while (begin < end) {
- ogg_page og;
-
- GST_DEBUG_OBJECT (ogg,
- "after seek, bisect %" G_GINT64_FORMAT ", begin %" G_GINT64_FORMAT
- ", end %" G_GINT64_FORMAT, bisect, begin, end);
-
- ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, &result);
- GST_LOG_OBJECT (ogg, "looking for next page returned %" G_GINT64_FORMAT,
- result);
-
- if (ret == GST_FLOW_LIMIT) {
- /* we hit the upper limit, go back a bit */
- if (bisect <= begin + 1) {
- end = begin; /* found it */
- } else {
- if (bisect == 0)
- goto seek_error;
-
- bisect -= CHUNKSIZE;
- if (bisect <= begin)
- bisect = begin + 1;
-
- gst_ogg_demux_seek (ogg, bisect);
- }
- } else if (ret == GST_FLOW_OK) {
- /* found offset of next ogg page */
- gint64 granulepos;
- GstClockTime granuletime;
- GstFormat format;
- GstOggPad *pad;
-
- GST_LOG_OBJECT (ogg, "found next ogg page at %" G_GINT64_FORMAT,
- result);
- granulepos = ogg_page_granulepos (&og);
- if (granulepos == -1) {
- GST_LOG_OBJECT (ogg, "granulepos of next page is -1");
- continue;
- }
-
- pad = gst_ogg_chain_get_stream (chain, ogg_page_serialno (&og));
- if (pad == NULL || pad->is_skeleton)
- continue;
-
- format = GST_FORMAT_TIME;
- if (!gst_ogg_pad_query_convert (pad,
- GST_FORMAT_DEFAULT, granulepos, &format,
- (gint64 *) & granuletime)) {
- GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
- granuletime = target;
- } else {
- if (granuletime < pad->start_time)
- continue;
- GST_LOG_OBJECT (ogg, "granulepos %" G_GINT64_FORMAT " maps to time %"
- GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime));
-
- granuletime -= pad->start_time;
- }
-
- GST_DEBUG_OBJECT (ogg,
- "found page with granule %" G_GINT64_FORMAT " and time %"
- GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime));
-
- if (granuletime < target) {
- best = result; /* raw offset of packet with granulepos */
- begin = ogg->offset; /* raw offset of next page */
- begintime = granuletime;
-
- if (target - begintime > GST_SECOND)
- break;
-
- bisect = begin; /* *not* begin + 1 */
- } else {
- if (bisect <= begin + 1) {
- end = begin; /* found it */
- } else {
- if (end == ogg->offset) { /* we're pretty close - we'd be stuck in */
- end = result;
- bisect -= CHUNKSIZE; /* an endless loop otherwise. */
- if (bisect <= begin)
- bisect = begin + 1;
- gst_ogg_demux_seek (ogg, bisect);
- } else {
- end = result;
- endtime = granuletime;
- break;
- }
- }
- }
- } else
- goto seek_error;
- }
- }
-
- ogg->offset = best;
- *rchain = chain;
-
- return TRUE;
-
-no_chains:
- {
- GST_DEBUG_OBJECT (ogg, "no chains");
- return FALSE;
- }
-seek_error:
- {
- GST_DEBUG_OBJECT (ogg, "got a seek error");
- return FALSE;
- }
-}
-
-/* does not take ownership of the event */
-static gboolean
-gst_ogg_demux_perform_seek (GstOggDemux * ogg, GstEvent * event)
-{
- GstOggChain *chain = NULL;
- gboolean res;
- gboolean flush, accurate;
- GstFormat format;
- gdouble rate;
- GstSeekFlags flags;
- GstSeekType cur_type, stop_type;
- gint64 cur, stop;
- gboolean update;
-
- if (event) {
- GST_DEBUG_OBJECT (ogg, "seek with event");
-
- gst_event_parse_seek (event, &rate, &format, &flags,
- &cur_type, &cur, &stop_type, &stop);
-
- /* we can only seek on time */
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (ogg, "can only seek on TIME");
- goto error;
- }
- } else {
- GST_DEBUG_OBJECT (ogg, "seek without event");
-
- flags = 0;
- rate = 1.0;
- }
-
- GST_DEBUG_OBJECT (ogg, "seek, rate %g", rate);
-
- flush = flags & GST_SEEK_FLAG_FLUSH;
- accurate = flags & GST_SEEK_FLAG_ACCURATE;
-
- /* first step is to unlock the streaming thread if it is
- * blocked in a chain call, we do this by starting the flush. because
- * we cannot yet hold any streaming lock, we have to protect the chains
- * with their own lock. */
- if (flush) {
- gint i;
-
- gst_pad_push_event (ogg->sinkpad, gst_event_new_flush_start ());
-
- GST_CHAIN_LOCK (ogg);
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
- gint j;
-
- for (j = 0; j < chain->streams->len; j++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j);
-
- gst_pad_push_event (GST_PAD (pad), gst_event_new_flush_start ());
- }
- }
- GST_CHAIN_UNLOCK (ogg);
- } else {
- gst_pad_pause_task (ogg->sinkpad);
- }
-
- /* now grab the stream lock so that streaming cannot continue, for
- * non flushing seeks when the element is in PAUSED this could block
- * forever. */
- GST_PAD_STREAM_LOCK (ogg->sinkpad);
-
- if (ogg->segment_running && !flush) {
- /* create the segment event to close the current segment */
- if ((chain = ogg->current_chain)) {
- GstEvent *newseg;
-
- newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate,
- GST_FORMAT_TIME, ogg->segment.start + chain->segment_start,
- ogg->segment.last_stop + chain->segment_start, ogg->segment.time);
-
- /* send segment on old chain, FIXME, must be sent from streaming thread. */
- gst_ogg_demux_send_event (ogg, newseg);
- }
- }
-
- if (event) {
- gst_segment_set_seek (&ogg->segment, rate, format, flags,
- cur_type, cur, stop_type, stop, &update);
- }
-
- GST_DEBUG_OBJECT (ogg, "segment positions set to %" GST_TIME_FORMAT "-%"
- GST_TIME_FORMAT, GST_TIME_ARGS (ogg->segment.start),
- GST_TIME_ARGS (ogg->segment.stop));
-
- /* we need to stop flushing on the srcpad as we're going to use it
- * next. We can do this as we have the STREAM lock now. */
- gst_pad_push_event (ogg->sinkpad, gst_event_new_flush_stop ());
-
- {
- gint i;
-
- /* reset all ogg streams now, need to do this from within the lock to
- * make sure the streaming thread is not messing with the stream */
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
- gst_ogg_chain_reset (chain);
- }
- }
-
- res = gst_ogg_demux_do_seek (ogg, ogg->segment.last_stop, accurate, &chain);
-
- /* seek failed, make sure we continue the current chain */
- if (!res) {
- chain = ogg->current_chain;
- }
-
- if (!chain)
- goto no_chain;
-
- /* now we have a new position, prepare for streaming again */
- {
- GstEvent *event;
- gint64 stop;
- gint64 start;
- gint64 last_stop, begin_time;
-
- /* we have to send the flush to the old chain, not the new one */
- if (flush)
- gst_ogg_demux_send_event (ogg, gst_event_new_flush_stop ());
-
- /* we need this to see how far inside the chain we need to start */
- if (chain->begin_time != GST_CLOCK_TIME_NONE)
- begin_time = chain->begin_time;
- else
- begin_time = 0;
-
- /* segment.start gives the start over all chains, we calculate the amount
- * of time into this chain we need to start */
- start = ogg->segment.start - begin_time;
- if (chain->segment_start != GST_CLOCK_TIME_NONE)
- start += chain->segment_start;
-
- if ((stop = ogg->segment.stop) == -1)
- stop = ogg->segment.duration;
-
- /* segment.stop gives the stop time over all chains, calculate the amount of
- * time we need to stop in this chain */
- if (stop != -1) {
- if (stop > begin_time)
- stop -= begin_time;
- else
- stop = 0;
- stop += chain->segment_start;
- /* we must stop when this chain ends and switch to the next chain to play
- * the remainder of the segment. */
- stop = MIN (stop, chain->segment_stop);
- }
-
- last_stop = ogg->segment.last_stop - begin_time;
- if (chain->segment_start != GST_CLOCK_TIME_NONE)
- last_stop += chain->segment_start;
-
- /* create the segment event we are going to send out */
- if (ogg->segment.rate >= 0.0)
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- ogg->segment.format, last_stop, stop, ogg->segment.time);
- else
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- ogg->segment.format, start, last_stop, ogg->segment.time);
-
- if (chain != ogg->current_chain) {
- /* switch to different chain, send segment on new chain */
- gst_ogg_demux_activate_chain (ogg, chain, event);
- } else {
- /* mark discont and send segment on current chain */
- gst_ogg_chain_mark_discont (chain);
- /* This event should be sent from the streaming thread (sink pad task) */
- if (ogg->newsegment)
- gst_event_unref (ogg->newsegment);
- ogg->newsegment = event;
- }
-
- /* notify start of new segment */
- if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) {
- gst_element_post_message (GST_ELEMENT (ogg),
- gst_message_new_segment_start (GST_OBJECT (ogg),
- GST_FORMAT_TIME, ogg->segment.last_stop));
- }
-
- ogg->segment_running = TRUE;
- /* restart our task since it might have been stopped when we did the
- * flush. */
- gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
- ogg->sinkpad);
- }
-
- /* streaming can continue now */
- GST_PAD_STREAM_UNLOCK (ogg->sinkpad);
-
- return res;
-
-error:
- {
- GST_DEBUG_OBJECT (ogg, "seek failed");
- return FALSE;
- }
-no_chain:
- {
- GST_DEBUG_OBJECT (ogg, "no chain to seek in");
- GST_PAD_STREAM_UNLOCK (ogg->sinkpad);
- return FALSE;
- }
-}
-
-/* finds each bitstream link one at a time using a bisection search
- * (has to begin by knowing the offset of the lb's initial page).
- * Recurses for each link so it can alloc the link storage after
- * finding them all, then unroll and fill the cache at the same time
- */
-static GstFlowReturn
-gst_ogg_demux_bisect_forward_serialno (GstOggDemux * ogg,
- gint64 begin, gint64 searched, gint64 end, GstOggChain * chain, glong m)
-{
- gint64 endsearched = end;
- gint64 next = end;
- ogg_page og;
- GstFlowReturn ret;
- gint64 offset;
- GstOggChain *nextchain;
-
- GST_LOG_OBJECT (ogg,
- "bisect begin: %" G_GINT64_FORMAT ", searched: %" G_GINT64_FORMAT
- ", end %" G_GINT64_FORMAT ", chain: %p", begin, searched, end, chain);
-
- /* the below guards against garbage seperating the last and
- * first pages of two links. */
- while (searched < endsearched) {
- gint64 bisect;
-
- if (endsearched - searched < CHUNKSIZE) {
- bisect = searched;
- } else {
- bisect = (searched + endsearched) / 2;
- }
-
- gst_ogg_demux_seek (ogg, bisect);
- ret = gst_ogg_demux_get_next_page (ogg, &og, -1, &offset);
-
- if (ret == GST_FLOW_UNEXPECTED) {
- endsearched = bisect;
- } else if (ret == GST_FLOW_OK) {
- glong serial = ogg_page_serialno (&og);
-
- if (!gst_ogg_chain_has_stream (chain, serial)) {
- endsearched = bisect;
- next = offset;
- } else {
- searched = offset + og.header_len + og.body_len;
- }
- } else
- return ret;
- }
-
- GST_LOG_OBJECT (ogg, "current chain ends at %" G_GINT64_FORMAT, searched);
-
- chain->end_offset = searched;
- ret = gst_ogg_demux_read_end_chain (ogg, chain);
- if (ret != GST_FLOW_OK)
- return ret;
-
- GST_LOG_OBJECT (ogg, "found begin at %" G_GINT64_FORMAT, next);
-
- gst_ogg_demux_seek (ogg, next);
- ret = gst_ogg_demux_read_chain (ogg, &nextchain);
- if (ret == GST_FLOW_UNEXPECTED) {
- nextchain = NULL;
- ret = GST_FLOW_OK;
- GST_LOG_OBJECT (ogg, "no next chain");
- } else if (ret != GST_FLOW_OK)
- goto done;
-
- if (searched < end && nextchain != NULL) {
- ret = gst_ogg_demux_bisect_forward_serialno (ogg, next, ogg->offset,
- end, nextchain, m + 1);
- if (ret != GST_FLOW_OK)
- goto done;
- }
- GST_LOG_OBJECT (ogg, "adding chain %p", chain);
-
- g_array_insert_val (ogg->chains, 0, chain);
-
-done:
- return ret;
-}
-
-/* read a chain from the ogg file. This code will
- * read all BOS pages and will create and return a GstOggChain
- * structure with the results.
- *
- * This function will also read N pages from each stream in the
- * chain and submit them to the decoders. When the decoder has
- * decoded the first buffer, we know the timestamp of the first
- * page in the chain.
- */
-static GstFlowReturn
-gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
-{
- GstFlowReturn ret;
- GstOggChain *chain = NULL;
- gint64 offset = ogg->offset;
- ogg_page op;
- gboolean done;
- gint i;
-
- GST_LOG_OBJECT (ogg, "reading chain at %" G_GINT64_FORMAT, offset);
-
- /* first read the BOS pages, do typefind on them, create
- * the decoders, send data to the decoders. */
- while (TRUE) {
- GstOggPad *pad;
- glong serial;
-
- ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
- if (ret != GST_FLOW_OK) {
- GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret);
- break;
- }
- if (!ogg_page_bos (&op)) {
- GST_WARNING_OBJECT (ogg, "page is not BOS page");
- break;
- }
-
- if (chain == NULL) {
- chain = gst_ogg_chain_new (ogg);
- chain->offset = offset;
- }
-
- serial = ogg_page_serialno (&op);
- if (gst_ogg_chain_get_stream (chain, serial) != NULL) {
- GST_WARNING_OBJECT (ogg, "found serial %08lx BOS page twice, ignoring",
- serial);
- continue;
- }
-
- pad = gst_ogg_chain_new_stream (chain, serial);
- gst_ogg_pad_submit_page (pad, &op);
- }
-
- if (ret != GST_FLOW_OK || chain == NULL) {
- if (ret != GST_FLOW_UNEXPECTED) {
- GST_WARNING_OBJECT (ogg, "failed to read chain");
- } else {
- GST_DEBUG_OBJECT (ogg, "done reading chains");
- }
- if (chain) {
- gst_ogg_chain_free (chain);
- }
- if (res_chain)
- *res_chain = NULL;
- return ret;
- }
-
- chain->have_bos = TRUE;
- GST_LOG_OBJECT (ogg, "read bos pages, init decoder now");
-
- /* now read pages until we receive a buffer from each of the
- * stream decoders, this will tell us the timestamp of the
- * first packet in the chain then */
-
- /* save the offset to the first non bos page in the chain: if searching for
- * pad->first_time we read past the end of the chain, we'll seek back to this
- * position
- */
- offset = ogg->offset;
-
- done = FALSE;
- while (!done) {
- glong serial;
- gboolean known_serial = FALSE;
- GstFlowReturn ret;
-
- serial = ogg_page_serialno (&op);
- done = TRUE;
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- GST_LOG_OBJECT (ogg, "serial %08x time %" GST_TIME_FORMAT, pad->serialno,
- GST_TIME_ARGS (pad->start_time));
-
- if (pad->serialno == serial) {
- known_serial = TRUE;
-
- /* submit the page now, this will fill in the start_time when the
- * internal decoder finds it */
- gst_ogg_pad_submit_page (pad, &op);
-
- if (!pad->is_skeleton && pad->start_time == -1 && ogg_page_eos (&op)) {
- /* got EOS on a pad before we could find its start_time.
- * We have no chance of finding a start_time for every pad so
- * stop searching for the other start_time(s).
- */
- done = TRUE;
- break;
- }
- }
- /* the timestamp will be filled in when we submit the pages */
- if (!pad->is_skeleton)
- done &= (pad->start_time != GST_CLOCK_TIME_NONE);
-
- GST_LOG_OBJECT (ogg, "done %08x now %d", pad->serialno, done);
- }
-
- /* we read a page not belonging to the current chain: seek back to the
- * beginning of the chain
- */
- if (!known_serial) {
- GST_LOG_OBJECT (ogg, "unknown serial %08lx", serial);
- gst_ogg_demux_seek (ogg, offset);
- break;
- }
-
- if (!done) {
- ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
- if (ret != GST_FLOW_OK)
- break;
- }
- }
- GST_LOG_OBJECT (ogg, "done reading chain");
- /* now we can fill in the missing info using queries */
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
- GstFormat target;
-
- if (pad->is_skeleton)
- continue;
-
- GST_LOG_OBJECT (ogg, "convert first granule %" G_GUINT64_FORMAT " to time ",
- pad->first_granule);
-
- target = GST_FORMAT_TIME;
- if (!gst_ogg_pad_query_convert (pad,
- GST_FORMAT_DEFAULT, pad->first_granule, &target,
- (gint64 *) & pad->first_time)) {
- GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
- } else {
- GST_LOG_OBJECT (ogg, "converted to first time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (pad->first_time));
- }
-
- pad->mode = GST_OGG_PAD_MODE_STREAMING;
- }
-
- if (res_chain)
- *res_chain = chain;
-
- return GST_FLOW_OK;
-}
-
-/* read the last pages from the ogg stream to get the final
- * page end_offsets.
- */
-static GstFlowReturn
-gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
-{
- gint64 begin = chain->end_offset;
- gint64 end = begin;
- gint64 last_granule = -1;
- GstOggPad *last_pad = NULL;
- GstFormat target;
- GstFlowReturn ret;
- gboolean done = FALSE;
- ogg_page og;
- gint i;
-
- while (!done) {
- begin -= CHUNKSIZE;
- if (begin < 0)
- begin = 0;
-
- gst_ogg_demux_seek (ogg, begin);
-
- /* now continue reading until we run out of data, if we find a page
- * start, we save it. It might not be the final page as there could be
- * another page after this one. */
- while (ogg->offset < end) {
- ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, NULL);
-
- if (ret == GST_FLOW_LIMIT)
- break;
- if (ret != GST_FLOW_OK)
- return ret;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- if (pad->is_skeleton)
- continue;
-
- if (pad->serialno == ogg_page_serialno (&og)) {
- gint64 granulepos = ogg_page_granulepos (&og);
-
- if (last_granule < granulepos) {
- last_granule = granulepos;
- last_pad = pad;
- }
- done = TRUE;
- break;
- }
- }
- }
- }
-
- target = GST_FORMAT_TIME;
- if (last_granule == -1 || !gst_ogg_pad_query_convert (last_pad,
- GST_FORMAT_DEFAULT, last_granule, &target,
- (gint64 *) & chain->segment_stop)) {
- GST_WARNING_OBJECT (ogg, "could not convert granulepos to time");
- chain->segment_stop = GST_CLOCK_TIME_NONE;
- }
-
- return GST_FLOW_OK;
-}
-
-/* find a pad with a given serial number
- */
-static GstOggPad *
-gst_ogg_demux_find_pad (GstOggDemux * ogg, int serialno)
-{
- GstOggPad *pad;
- gint i;
-
- /* first look in building chain if any */
- if (ogg->building_chain) {
- pad = gst_ogg_chain_get_stream (ogg->building_chain, serialno);
- if (pad)
- return pad;
- }
-
- /* then look in current chain if any */
- if (ogg->current_chain) {
- pad = gst_ogg_chain_get_stream (ogg->current_chain, serialno);
- if (pad)
- return pad;
- }
-
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
- pad = gst_ogg_chain_get_stream (chain, serialno);
- if (pad)
- return pad;
- }
- return NULL;
-}
-
-/* find a chain with a given serial number
- */
-static GstOggChain *
-gst_ogg_demux_find_chain (GstOggDemux * ogg, int serialno)
-{
- GstOggPad *pad;
-
- pad = gst_ogg_demux_find_pad (ogg, serialno);
- if (pad) {
- return pad->chain;
- }
- return NULL;
-}
-
-/* returns TRUE if all streams have valid start time */
-static gboolean
-gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain)
-{
- gint i;
- gboolean res = TRUE;
-
- chain->total_time = GST_CLOCK_TIME_NONE;
- chain->segment_start = G_MAXUINT64;
-
- GST_DEBUG_OBJECT (ogg, "trying to collect chain info");
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- if (pad->is_skeleton)
- continue;
-
- /* can do this if the pad start time is not defined */
- if (pad->start_time == GST_CLOCK_TIME_NONE)
- res = FALSE;
- else
- chain->segment_start = MIN (chain->segment_start, pad->start_time);
- }
-
- if (chain->segment_stop != GST_CLOCK_TIME_NONE
- && chain->segment_start != G_MAXUINT64)
- chain->total_time = chain->segment_stop - chain->segment_start;
-
- GST_DEBUG_OBJECT (ogg, "return %d", res);
-
- return res;
-}
-
-static void
-gst_ogg_demux_collect_info (GstOggDemux * ogg)
-{
- gint i;
-
- /* collect all info */
- ogg->total_time = 0;
-
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
- chain->begin_time = ogg->total_time;
-
- gst_ogg_demux_collect_chain_info (ogg, chain);
-
- ogg->total_time += chain->total_time;
- }
- gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time);
-}
-
-/* find all the chains in the ogg file, this reads the first and
- * last page of the ogg stream, if they match then the ogg file has
- * just one chain, else we do a binary search for all chains.
- */
-static GstFlowReturn
-gst_ogg_demux_find_chains (GstOggDemux * ogg)
-{
- ogg_page og;
- GstPad *peer;
- GstFormat format;
- gboolean res;
- gulong serialno;
- GstOggChain *chain;
- GstFlowReturn ret;
-
- /* get peer to figure out length */
- if ((peer = gst_pad_get_peer (ogg->sinkpad)) == NULL)
- goto no_peer;
-
- /* find length to read last page, we store this for later use. */
- format = GST_FORMAT_BYTES;
- res = gst_pad_query_duration (peer, &format, &ogg->length);
- gst_object_unref (peer);
- if (!res || ogg->length <= 0)
- goto no_length;
-
- GST_DEBUG_OBJECT (ogg, "file length %" G_GINT64_FORMAT, ogg->length);
-
- /* read chain from offset 0, this is the first chain of the
- * ogg file. */
- gst_ogg_demux_seek (ogg, 0);
- ret = gst_ogg_demux_read_chain (ogg, &chain);
- if (ret != GST_FLOW_OK)
- goto no_first_chain;
-
- /* read page from end offset, we use this page to check if its serial
- * number is contained in the first chain. If this is the case then
- * this ogg is not a chained ogg and we can skip the scanning. */
- gst_ogg_demux_seek (ogg, ogg->length);
- ret = gst_ogg_demux_get_prev_page (ogg, &og, NULL);
- if (ret != GST_FLOW_OK)
- goto no_last_page;
-
- serialno = ogg_page_serialno (&og);
-
- if (!gst_ogg_chain_has_stream (chain, serialno)) {
- /* the last page is not in the first stream, this means we should
- * find all the chains in this chained ogg. */
- ret =
- gst_ogg_demux_bisect_forward_serialno (ogg, 0, 0, ogg->length, chain,
- 0);
- } else {
- /* we still call this function here but with an empty range so that
- * we can reuse the setup code in this routine. */
- ret =
- gst_ogg_demux_bisect_forward_serialno (ogg, 0, ogg->length, ogg->length,
- chain, 0);
- }
- if (ret != GST_FLOW_OK)
- goto done;
-
- /* all fine, collect and print */
- gst_ogg_demux_collect_info (ogg);
-
- /* dump our chains and streams */
- gst_ogg_print (ogg);
-
-done:
- return ret;
-
- /*** error cases ***/
-no_peer:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("we don't have a peer"));
- return GST_FLOW_NOT_LINKED;
- }
-no_length:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get file length"));
- return GST_FLOW_NOT_SUPPORTED;
- }
-no_first_chain:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get first chain"));
- return GST_FLOW_ERROR;
- }
-no_last_page:
- {
- GST_DEBUG_OBJECT (ogg, "can't get last page");
- if (chain)
- gst_ogg_chain_free (chain);
- return ret;
- }
-}
-
-static GstFlowReturn
-gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
-{
- GstOggPad *pad;
- gint64 granule;
- guint serialno;
- GstFlowReturn result = GST_FLOW_OK;
-
- serialno = ogg_page_serialno (page);
- granule = ogg_page_granulepos (page);
-
- GST_LOG_OBJECT (ogg,
- "processing ogg page (serial %08x, pageno %ld, granulepos %"
- G_GINT64_FORMAT ", bos %d)",
- serialno, ogg_page_pageno (page), granule, ogg_page_bos (page));
-
- if (ogg_page_bos (page)) {
- GstOggChain *chain;
-
- /* first page */
- /* see if we know about the chain already */
- chain = gst_ogg_demux_find_chain (ogg, serialno);
- if (chain) {
- GstEvent *event;
-
- /* create the newsegment event we are going to send out */
- event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
- GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
- chain->begin_time);
-
- GST_DEBUG_OBJECT (ogg,
- "segment: start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT
- ", time %" GST_TIME_FORMAT, GST_TIME_ARGS (chain->segment_start),
- GST_TIME_ARGS (chain->segment_stop),
- GST_TIME_ARGS (chain->begin_time));
-
- /* activate it as it means we have a non-header */
- gst_ogg_demux_activate_chain (ogg, chain, event);
- pad = gst_ogg_demux_find_pad (ogg, serialno);
- } else {
- GstClockTime chain_time;
- GstOggChain *current_chain;
- gint64 current_time;
-
- /* this can only happen in non-seekabe mode */
- if (ogg->seekable)
- goto unknown_chain;
-
- current_chain = ogg->current_chain;
- current_time = ogg->segment.last_stop;
-
- if (current_chain) {
- /* remove existing pads */
- gst_ogg_demux_deactivate_current_chain (ogg);
- }
- /* time of new chain is current time */
- chain_time = current_time;
-
- if (ogg->building_chain == NULL) {
- GstOggChain *newchain;
-
- newchain = gst_ogg_chain_new (ogg);
- newchain->offset = 0;
- /* set new chain begin time aligned with end time of old chain */
- newchain->begin_time = chain_time;
- GST_DEBUG_OBJECT (ogg, "new chain, begin time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain_time));
-
- /* and this is the one we are building now */
- ogg->building_chain = newchain;
- }
- pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno);
- }
- } else {
- pad = gst_ogg_demux_find_pad (ogg, serialno);
- }
- if (pad) {
- result = gst_ogg_pad_submit_page (pad, page);
- } else {
- /* no pad, this is pretty fatal. This means an ogg page without bos
- * has been seen for this serialno. could just ignore it too... */
- goto unknown_pad;
- }
- return result;
-
- /* ERRORS */
-unknown_chain:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
- (NULL), ("unknown ogg chain for serial %08x detected", serialno));
- return GST_FLOW_ERROR;
- }
-unknown_pad:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
- (NULL), ("unknown ogg pad for serial %08x detected", serialno));
- return GST_FLOW_ERROR;
- }
-}
-
-/* streaming mode, receive a buffer, parse it, create pads for
- * the serialno, submit pages and packets to the oggpads
- */
-static GstFlowReturn
-gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstOggDemux *ogg;
- gint ret;
- GstFlowReturn result = GST_FLOW_OK;
-
- ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
-
- GST_DEBUG_OBJECT (ogg, "chain");
- result = gst_ogg_demux_submit_buffer (ogg, buffer);
-
- while (result == GST_FLOW_OK) {
- ogg_page page;
-
- ret = ogg_sync_pageout (&ogg->sync, &page);
- if (ret == 0)
- /* need more data */
- break;
- if (ret == -1) {
- /* discontinuity in the pages */
- GST_DEBUG_OBJECT (ogg, "discont in page found, continuing");
- } else {
- result = gst_ogg_demux_handle_page (ogg, &page);
- }
- }
- return result;
-}
-
-static void
-gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event)
-{
- GstOggChain *chain = ogg->current_chain;
-
- if (chain) {
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i);
-
- gst_event_ref (event);
- GST_DEBUG_OBJECT (ogg, "Pushing event on pad %p", pad);
- gst_pad_push_event (GST_PAD (pad), event);
- }
- }
- gst_event_unref (event);
-}
-
-static GstFlowReturn
-gst_ogg_demux_combine_flows (GstOggDemux * ogg, GstOggPad * pad,
- GstFlowReturn ret)
-{
- GstOggChain *chain;
-
- /* store the value */
- pad->last_ret = ret;
-
- /* any other error that is not-linked can be returned right
- * away */
- if (ret != GST_FLOW_NOT_LINKED)
- goto done;
-
- /* only return NOT_LINKED if all other pads returned NOT_LINKED */
- chain = ogg->current_chain;
- if (chain) {
- gint i;
-
- for (i = 0; i < chain->streams->len; i++) {
- GstOggPad *opad = g_array_index (chain->streams, GstOggPad *, i);
-
- ret = opad->last_ret;
- /* some other return value (must be SUCCESS but we can return
- * other values as well) */
- if (ret != GST_FLOW_NOT_LINKED)
- goto done;
- }
- /* if we get here, all other pads were unlinked and we return
- * NOT_LINKED then */
- }
-done:
- return ret;
-}
-
-static GstFlowReturn
-gst_ogg_demux_loop_forward (GstOggDemux * ogg)
-{
- GstFlowReturn ret;
- GstBuffer *buffer;
-
- if (ogg->offset == ogg->length) {
- GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
- " == %" G_GINT64_FORMAT, ogg->offset, ogg->length);
- ret = GST_FLOW_UNEXPECTED;
- goto done;
- }
-
- GST_LOG_OBJECT (ogg, "pull data %" G_GINT64_FORMAT, ogg->offset);
- ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer);
- if (ret != GST_FLOW_OK) {
- GST_LOG_OBJECT (ogg, "Failed pull_range");
- goto done;
- }
-
- ogg->offset += GST_BUFFER_SIZE (buffer);
-
- if (G_UNLIKELY (ogg->newsegment)) {
- gst_ogg_demux_send_event (ogg, ogg->newsegment);
- ogg->newsegment = NULL;
- }
-
- ret = gst_ogg_demux_chain (ogg->sinkpad, buffer);
- if (ret != GST_FLOW_OK) {
- GST_LOG_OBJECT (ogg, "Failed demux_chain");
- goto done;
- }
-
- /* check for the end of the segment */
- if (ogg->segment.stop != -1 && ogg->segment.last_stop != -1) {
- if (ogg->segment.last_stop > ogg->segment.stop) {
- ret = GST_FLOW_UNEXPECTED;
- goto done;
- }
- }
-done:
- return ret;
-}
-
-/* reverse mode.
- *
- * We read the pages backwards and send the packets forwards. The first packet
- * in the page will be pushed with the DISCONT flag set.
- *
- * Special care has to be taken for continued pages, which we can only decode
- * when we have the previous page(s).
- */
-static GstFlowReturn
-gst_ogg_demux_loop_reverse (GstOggDemux * ogg)
-{
- GstFlowReturn ret;
- ogg_page page;
- gint64 offset;
-
- if (ogg->offset == 0) {
- GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT
- " == 0", ogg->offset);
- ret = GST_FLOW_UNEXPECTED;
- goto done;
- }
-
- GST_LOG_OBJECT (ogg, "read page from %" G_GINT64_FORMAT, ogg->offset);
- ret = gst_ogg_demux_get_prev_page (ogg, &page, &offset);
- if (ret != GST_FLOW_OK)
- goto done;
-
- ogg->offset = offset;
-
- if (G_UNLIKELY (ogg->newsegment)) {
- gst_ogg_demux_send_event (ogg, ogg->newsegment);
- ogg->newsegment = NULL;
- }
-
- ret = gst_ogg_demux_handle_page (ogg, &page);
- if (ret != GST_FLOW_OK)
- goto done;
-
- /* check for the end of the segment */
- if (ogg->segment.start != -1 && ogg->segment.last_stop != -1) {
- if (ogg->segment.last_stop <= ogg->segment.start) {
- ret = GST_FLOW_UNEXPECTED;
- goto done;
- }
- }
-done:
- return ret;
-}
-
-/* random access code
- *
- * - first find all the chains and streams by scanning the file.
- * - then get and chain buffers, just like the streaming case.
- * - when seeking, we can use the chain info to perform the seek.
- */
-static void
-gst_ogg_demux_loop (GstOggPad * pad)
-{
- GstOggDemux *ogg;
- GstFlowReturn ret;
- GstEvent *event;
-
- ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad));
-
- if (ogg->need_chains) {
- gboolean res;
-
- /* this is the only place where we write chains and thus need to lock. */
- GST_CHAIN_LOCK (ogg);
- ret = gst_ogg_demux_find_chains (ogg);
- GST_CHAIN_UNLOCK (ogg);
- if (ret != GST_FLOW_OK)
- goto chain_read_failed;
-
- ogg->need_chains = FALSE;
-
- GST_OBJECT_LOCK (ogg);
- ogg->running = TRUE;
- event = ogg->event;
- ogg->event = NULL;
- GST_OBJECT_UNLOCK (ogg);
-
- /* and seek to configured positions without FLUSH */
- res = gst_ogg_demux_perform_seek (ogg, event);
- if (event)
- gst_event_unref (event);
-
- if (!res)
- goto seek_failed;
- }
-
- if (ogg->segment.rate >= 0.0)
- ret = gst_ogg_demux_loop_forward (ogg);
- else
- ret = gst_ogg_demux_loop_reverse (ogg);
-
- if (ret != GST_FLOW_OK)
- goto pause;
-
- return;
-
- /* ERRORS */
-chain_read_failed:
- {
- /* error was posted */
- goto pause;
- }
-seek_failed:
- {
- GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL),
- ("failed to start demuxing ogg"));
- ret = GST_FLOW_ERROR;
- goto pause;
- }
-pause:
- {
- const gchar *reason = gst_flow_get_name (ret);
-
- GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason);
- ogg->segment_running = FALSE;
- gst_pad_pause_task (ogg->sinkpad);
-
- if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
- if (ret == GST_FLOW_UNEXPECTED) {
- /* perform EOS logic */
- if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) {
- gint64 stop;
-
- /* for segment playback we need to post when (in stream time)
- * we stopped, this is either stop (when set) or the duration. */
- if ((stop = ogg->segment.stop) == -1)
- stop = ogg->segment.duration;
-
- GST_LOG_OBJECT (ogg, "Sending segment done, at end of segment");
- gst_element_post_message (GST_ELEMENT (ogg),
- gst_message_new_segment_done (GST_OBJECT (ogg), GST_FORMAT_TIME,
- stop));
- } else {
- /* normal playback, send EOS to all linked pads */
- GST_LOG_OBJECT (ogg, "Sending EOS, at end of stream");
- gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
- }
- } else {
- GST_ELEMENT_ERROR (ogg, STREAM, FAILED,
- (_("Internal data stream error.")),
- ("stream stopped, reason %s", reason));
- gst_ogg_demux_send_event (ogg, gst_event_new_eos ());
- }
- }
- return;
- }
-}
-
-static void
-gst_ogg_demux_clear_chains (GstOggDemux * ogg)
-{
- gint i;
-
- gst_ogg_demux_deactivate_current_chain (ogg);
-
- GST_CHAIN_LOCK (ogg);
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
- gst_ogg_chain_free (chain);
- }
- ogg->chains = g_array_set_size (ogg->chains, 0);
- GST_CHAIN_UNLOCK (ogg);
-}
-
-/* this function is called when the pad is activated and should start
- * processing data.
- *
- * We check if we can do random access to decide if we work push or
- * pull based.
- */
-static gboolean
-gst_ogg_demux_sink_activate (GstPad * sinkpad)
-{
- if (gst_pad_check_pull_range (sinkpad)) {
- GST_DEBUG_OBJECT (sinkpad, "activating pull");
- return gst_pad_activate_pull (sinkpad, TRUE);
- } else {
- GST_DEBUG_OBJECT (sinkpad, "activating push");
- return gst_pad_activate_push (sinkpad, TRUE);
- }
-}
-
-/* this function gets called when we activate ourselves in push mode.
- * We cannot seek (ourselves) in the stream */
-static gboolean
-gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active)
-{
- GstOggDemux *ogg;
-
- ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
-
- ogg->seekable = FALSE;
-
- return TRUE;
-}
-
-/* this function gets called when we activate ourselves in pull mode.
- * We can perform random access to the resource and we start a task
- * to start reading */
-static gboolean
-gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
-{
- GstOggDemux *ogg;
-
- ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad));
-
- if (active) {
- ogg->need_chains = TRUE;
- ogg->seekable = TRUE;
-
- return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop,
- sinkpad);
- } else {
- return gst_pad_stop_task (sinkpad);
- }
-}
-
-static GstStateChangeReturn
-gst_ogg_demux_change_state (GstElement * element, GstStateChange transition)
-{
- GstOggDemux *ogg;
- GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
- ogg = GST_OGG_DEMUX (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- ogg->basetime = 0;
- ogg->have_fishead = FALSE;
- ogg_sync_init (&ogg->sync);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- ogg_sync_reset (&ogg->sync);
- ogg->current_granule = -1;
- ogg->running = FALSE;
- ogg->segment_running = FALSE;
- gst_segment_init (&ogg->segment, GST_FORMAT_TIME);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- result = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_ogg_demux_clear_chains (ogg);
- GST_OBJECT_LOCK (ogg);
- ogg->running = FALSE;
- ogg->segment_running = FALSE;
- ogg->have_fishead = FALSE;
- GST_OBJECT_UNLOCK (ogg);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- ogg_sync_clear (&ogg->sync);
- break;
- default:
- break;
- }
- return result;
-}
-
-static GstClockTime
-gst_annodex_granule_to_time (gint64 granulepos, gint64 granulerate_n,
- gint64 granulerate_d, guint8 granuleshift)
-{
- gint64 keyindex, keyoffset;
- gint64 granulerate;
- GstClockTime res;
-
- if (granulepos == 0 || granulerate_n == 0 || granulerate_d == 0)
- return 0;
-
- if (granuleshift != 0) {
- keyindex = granulepos >> granuleshift;
- keyoffset = granulepos - (keyindex << granuleshift);
- granulepos = keyindex + keyoffset;
- }
-
- /* GST_SECOND / (granulerate_n / granulerate_d) */
- granulerate = gst_util_uint64_scale (GST_SECOND,
- granulerate_d, granulerate_n);
- res = gst_util_uint64_scale (granulepos, granulerate, 1);
- return res;
-}
-
-gboolean
-gst_ogg_demux_plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_debug, "oggdemux", 0, "ogg demuxer");
- GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_setup_debug, "oggdemux_setup", 0,
- "ogg demuxer setup stage when parsing pipeline");
-
-#if ENABLE_NLS
- GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
- LOCALEDIR);
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif
-
- return gst_element_register (plugin, "oggdemux", GST_RANK_PRIMARY,
- GST_TYPE_OGG_DEMUX);
-}
-
-/* prints all info about the element */
-#undef GST_CAT_DEFAULT
-#define GST_CAT_DEFAULT gst_ogg_demux_setup_debug
-
-#ifdef GST_DISABLE_GST_DEBUG
-
-static void
-gst_ogg_print (GstOggDemux * ogg)
-{
- /* NOP */
-}
-
-#else /* !GST_DISABLE_GST_DEBUG */
-
-static void
-gst_ogg_print (GstOggDemux * ogg)
-{
- guint j, i;
-
- GST_INFO_OBJECT (ogg, "%u chains", ogg->chains->len);
- GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (ogg->total_time));
-
- for (i = 0; i < ogg->chains->len; i++) {
- GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i);
-
- GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len);
- GST_INFO_OBJECT (ogg, " offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT,
- chain->offset, chain->end_offset);
- GST_INFO_OBJECT (ogg, " begin time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->begin_time));
- GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->total_time));
- GST_INFO_OBJECT (ogg, " segment start: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->segment_start));
- GST_INFO_OBJECT (ogg, " segment stop: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (chain->segment_stop));
-
- for (j = 0; j < chain->streams->len; j++) {
- GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j);
-
- GST_INFO_OBJECT (ogg, " stream %08x:", stream->serialno);
- GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (stream->start_time));
- GST_INFO_OBJECT (ogg, " first granulepos: %" G_GINT64_FORMAT,
- stream->first_granule);
- GST_INFO_OBJECT (ogg, " first time: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (stream->first_time));
- }
- }
-}
-#endif /* GST_DISABLE_GST_DEBUG */
--- a/gst_plugins_base/ext/ogg/gstoggdemux.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- *
- * gstoggdemux.c: ogg stream demuxer
- *
- * 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 __GST_OGG_DEMUX_H__
-#define __GST_OGG_DEMUX_H__
-
-#include <ogg/ogg.h>
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_OGG_PAD (gst_ogg_pad_get_type())
-#define GST_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PAD, GstOggPad))
-#define GST_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PAD, GstOggPad))
-#define GST_IS_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PAD))
-#define GST_IS_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PAD))
-
-typedef struct _GstOggPad GstOggPad;
-typedef struct _GstOggPadClass GstOggPadClass;
-
-#define GST_TYPE_OGG_DEMUX (gst_ogg_demux_get_type())
-#define GST_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_DEMUX, GstOggDemux))
-#define GST_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_DEMUX, GstOggDemux))
-#define GST_IS_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_DEMUX))
-#define GST_IS_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_DEMUX))
-
-static GType gst_ogg_demux_get_type (void);
-
-typedef struct _GstOggDemux GstOggDemux;
-typedef struct _GstOggDemuxClass GstOggDemuxClass;
-typedef struct _GstOggChain GstOggChain;
-
-/* all information needed for one ogg chain (relevant for chained bitstreams) */
-struct _GstOggChain
-{
- GstOggDemux *ogg;
-
- gint64 offset; /* starting offset of chain */
- gint64 end_offset; /* end offset of chain */
- gint64 bytes; /* number of bytes */
-
- gboolean have_bos;
-
- GArray *streams;
-
- GstClockTime total_time; /* the total time of this chain, this is the MAX of
- the totals of all streams */
- GstClockTime begin_time; /* when this chain starts in the stream */
-
- GstClockTime segment_start; /* the timestamp of the first sample, this is the MIN of
- the start times of all streams. */
- GstClockTime segment_stop; /* the timestamp of the last page, this is the MAX of the
- streams. */
-};
-
-/* different modes for the pad */
-typedef enum
-{
- GST_OGG_PAD_MODE_INIT, /* we are feeding our internal decoder to get info */
- GST_OGG_PAD_MODE_STREAMING, /* we are streaming buffers to the outside */
-} GstOggPadMode;
-
-/* all information needed for one ogg stream */
-struct _GstOggPad
-{
- GstPad pad; /* subclass GstPad */
-
- gboolean have_type;
- GstOggPadMode mode;
-
- GstPad *elem_pad; /* sinkpad of internal element */
- GstElement *element; /* internal element */
- GstPad *elem_out; /* our sinkpad to receive buffers form the internal element */
-
- GstOggChain *chain; /* the chain we are part of */
- GstOggDemux *ogg; /* the ogg demuxer we are part of */
-
- GList *headers;
-
- gboolean is_skeleton;
- gboolean have_fisbone;
- gint64 granulerate_n;
- gint64 granulerate_d;
- guint32 preroll;
- guint granuleshift;
-
- gint serialno;
- gint64 packetno;
- gint64 current_granule;
-
- GstClockTime start_time; /* the timestamp of the first sample */
-
- gint64 first_granule; /* the granulepos of first page == first sample in next page */
- GstClockTime first_time; /* the timestamp of the second page or granuletime of first page */
-
- ogg_stream_state stream;
- GList *continued;
-
- gboolean discont;
- GstFlowReturn last_ret; /* last return of _pad_push() */
-
- gboolean dynamic; /* True if the internal element had dynamic pads */
- guint padaddedid; /* The signal id for element::pad-added */
-};
-
-struct _GstOggPadClass
-{
- GstPadClass parent_class;
-};
-
-#define GST_CHAIN_LOCK(ogg) g_mutex_lock((ogg)->chain_lock)
-#define GST_CHAIN_UNLOCK(ogg) g_mutex_unlock((ogg)->chain_lock)
-
-/**
- * GstOggDemux:
- *
- * The ogg demuxer object structure.
- */
-struct _GstOggDemux
-{
- GstElement element;
-
- GstPad *sinkpad;
-
- gint64 length;
- gint64 offset;
-
- gboolean seekable;
- gboolean running;
-
- gboolean need_chains;
-
- /* state */
- GMutex *chain_lock; /* we need the lock to protect the chains */
- GArray *chains; /* list of chains we know */
- GstClockTime total_time;
-
- GstOggChain *current_chain;
- GstOggChain *building_chain;
-
- /* playback start/stop positions */
- GstSegment segment;
- gboolean segment_running;
-
- GstEvent *event;
- GstEvent *newsegment; /* pending newsegment to be sent from _loop */
-
- gint64 current_granule;
-
- /* annodex stuff */
- gboolean have_fishead;
- gint64 basetime;
-
- /* ogg stuff */
- ogg_sync_state sync;
-};
-
-struct _GstOggDemuxClass
-{
- GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_OGG_DEMUX_H__ */
--- a/gst_plugins_base/ext/ogg/gstoggmux.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1627 +0,0 @@
-/* OGG muxer plugin for GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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 <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
-
-#include "gstoggmux.h"
-
-/* memcpy - if someone knows a way to get rid of it, please speak up
- * note: the ogg docs even say you need this... */
-#include <string.h>
-#include <time.h>
-#include <stdlib.h> /* rand, srand, atoi */
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_mux_debug);
-#define GST_CAT_DEFAULT gst_ogg_mux_debug
-
-/* This isn't generally what you'd want with an end-time macro, because
- technically the end time of a buffer with invalid duration is invalid. But
- for sorting ogg pages this is what we want. */
-#define GST_BUFFER_END_TIME(buf) \
- (GST_BUFFER_DURATION_IS_VALID (buf) \
- ? GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf) \
- : GST_BUFFER_TIMESTAMP (buf))
-
-#define GST_GP_FORMAT "[gp %8" G_GINT64_FORMAT "]"
-
-typedef enum
-{
- GST_OGG_FLAG_BOS = GST_ELEMENT_FLAG_LAST,
- GST_OGG_FLAG_EOS
-}
-GstOggFlag;
-
-/* elementfactory information */
-static const GstElementDetails gst_ogg_mux_details =
-GST_ELEMENT_DETAILS ("Ogg muxer",
- "Codec/Muxer",
- "mux ogg streams (info about ogg: http://xiph.org)",
- "Wim Taymans <wim@fluendo.com>");
-
-/* OggMux signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-/* set to 0.5 seconds by default */
-#define DEFAULT_MAX_DELAY G_GINT64_CONSTANT(500000000)
-#define DEFAULT_MAX_PAGE_DELAY G_GINT64_CONSTANT(500000000)
-enum
-{
- ARG_0,
- ARG_MAX_DELAY,
- ARG_MAX_PAGE_DELAY,
-};
-
-static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/ogg")
- );
-
-static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d",
- GST_PAD_SINK,
- GST_PAD_REQUEST,
- GST_STATIC_CAPS ("video/x-theora; "
- "audio/x-vorbis; audio/x-flac; audio/x-speex; "
- "application/x-ogm-video; application/x-ogm-audio; video/x-dirac; "
- "video/x-smoke; text/x-cmml, encoded = (boolean) TRUE")
- );
-
-static void gst_ogg_mux_base_init (gpointer g_class);
-static void gst_ogg_mux_class_init (GstOggMuxClass * klass);
-static void gst_ogg_mux_init (GstOggMux * ogg_mux);
-static void gst_ogg_mux_finalize (GObject * object);
-
-static GstFlowReturn
-gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux);
-static gboolean gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event);
-static GstPad *gst_ogg_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
-static void gst_ogg_mux_release_pad (GstElement * element, GstPad * pad);
-
-static void gst_ogg_mux_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_ogg_mux_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static GstStateChangeReturn gst_ogg_mux_change_state (GstElement * element,
- GstStateChange transition);
-
-static GstElementClass *parent_class = NULL;
-
-/*static guint gst_ogg_mux_signals[LAST_SIGNAL] = { 0 }; */
-
-GType
-gst_ogg_mux_get_type (void)
-{
- static GType ogg_mux_type = 0;
-
- if (G_UNLIKELY (ogg_mux_type == 0)) {
- static const GTypeInfo ogg_mux_info = {
- sizeof (GstOggMuxClass),
- gst_ogg_mux_base_init,
- NULL,
- (GClassInitFunc) gst_ogg_mux_class_init,
- NULL,
- NULL,
- sizeof (GstOggMux),
- 0,
- (GInstanceInitFunc) gst_ogg_mux_init,
- };
-
- ogg_mux_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstOggMux", &ogg_mux_info,
- 0);
- }
- return ogg_mux_type;
-}
-
-static void
-gst_ogg_mux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
-
- gst_element_class_set_details (element_class, &gst_ogg_mux_details);
-}
-
-static void
-gst_ogg_mux_class_init (GstOggMuxClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_ogg_mux_finalize;
- gobject_class->get_property = gst_ogg_mux_get_property;
- gobject_class->set_property = gst_ogg_mux_set_property;
-
- gstelement_class->request_new_pad = gst_ogg_mux_request_new_pad;
- gstelement_class->release_pad = gst_ogg_mux_release_pad;
-
- g_object_class_install_property (gobject_class, ARG_MAX_DELAY,
- g_param_spec_uint64 ("max-delay", "Max delay",
- "Maximum delay in multiplexing streams", 0, G_MAXUINT64,
- DEFAULT_MAX_DELAY, (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_MAX_PAGE_DELAY,
- g_param_spec_uint64 ("max-page-delay", "Max page delay",
- "Maximum delay for sending out a page", 0, G_MAXUINT64,
- DEFAULT_MAX_PAGE_DELAY, (GParamFlags) G_PARAM_READWRITE));
-
- gstelement_class->change_state = gst_ogg_mux_change_state;
-
-}
-
-#if 0
-static const GstEventMask *
-gst_ogg_mux_get_sink_event_masks (GstPad * pad)
-{
- static const GstEventMask gst_ogg_mux_sink_event_masks[] = {
- {GST_EVENT_EOS, 0},
- {GST_EVENT_DISCONTINUOUS, 0},
- {0,}
- };
-
- return gst_ogg_mux_sink_event_masks;
-}
-#endif
-
-static void
-gst_ogg_mux_clear (GstOggMux * ogg_mux)
-{
- ogg_mux->pulling = NULL;
- ogg_mux->need_headers = TRUE;
- ogg_mux->max_delay = DEFAULT_MAX_DELAY;
- ogg_mux->max_page_delay = DEFAULT_MAX_PAGE_DELAY;
- ogg_mux->delta_pad = NULL;
- ogg_mux->offset = 0;
- ogg_mux->next_ts = 0;
- ogg_mux->last_ts = GST_CLOCK_TIME_NONE;
-}
-
-static void
-gst_ogg_mux_init (GstOggMux * ogg_mux)
-{
- GstElementClass *klass = GST_ELEMENT_GET_CLASS (ogg_mux);
-
- ogg_mux->srcpad =
- gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
- "src"), "src");
- gst_pad_set_event_function (ogg_mux->srcpad, gst_ogg_mux_handle_src_event);
- gst_element_add_pad (GST_ELEMENT (ogg_mux), ogg_mux->srcpad);
-
- GST_OBJECT_FLAG_SET (GST_ELEMENT (ogg_mux), GST_OGG_FLAG_BOS);
-
- /* seed random number generator for creation of serial numbers */
- srand (time (NULL));
-
- ogg_mux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (ogg_mux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_ogg_mux_collected),
- ogg_mux);
-
- gst_ogg_mux_clear (ogg_mux);
-}
-
-static void
-gst_ogg_mux_finalize (GObject * object)
-{
- GstOggMux *ogg_mux;
-
- ogg_mux = GST_OGG_MUX (object);
-
- if (ogg_mux->collect) {
- gst_object_unref (ogg_mux->collect);
- ogg_mux->collect = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_ogg_mux_ogg_pad_destroy_notify (GstCollectData * data)
-{
- GstOggPad *oggpad = (GstOggPad *) data;
- GstBuffer *buf;
-
- ogg_stream_clear (&oggpad->stream);
-
- if (oggpad->pagebuffers) {
- while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
- gst_buffer_unref (buf);
- }
- g_queue_free (oggpad->pagebuffers);
- oggpad->pagebuffers = NULL;
- }
-}
-
-static GstPadLinkReturn
-gst_ogg_mux_sinkconnect (GstPad * pad, GstPad * peer)
-{
- GstOggMux *ogg_mux;
-
- ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
-
- GST_DEBUG_OBJECT (ogg_mux, "sinkconnect triggered on %s", GST_PAD_NAME (pad));
-
- gst_object_unref (ogg_mux);
-
- return GST_PAD_LINK_OK;
-}
-
-static GstPad *
-gst_ogg_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * req_name)
-{
- GstOggMux *ogg_mux;
- GstPad *newpad;
- GstElementClass *klass;
-
- g_return_val_if_fail (templ != NULL, NULL);
-
- if (templ->direction != GST_PAD_SINK)
- goto wrong_direction;
-
- g_return_val_if_fail (GST_IS_OGG_MUX (element), NULL);
- ogg_mux = GST_OGG_MUX (element);
-
- klass = GST_ELEMENT_GET_CLASS (element);
-
- if (templ != gst_element_class_get_pad_template (klass, "sink_%d"))
- goto wrong_template;
-
- {
- gint serial;
- gchar *name;
-
- if (req_name == NULL || strlen (req_name) < 6) {
- /* no name given when requesting the pad, use random serial number */
- serial = rand ();
- } else {
- /* parse serial number from requested padname */
- serial = atoi (&req_name[5]);
- }
- /* create new pad with the name */
- GST_DEBUG_OBJECT (ogg_mux, "Creating new pad for serial %d", serial);
- name = g_strdup_printf ("sink_%d", serial);
- newpad = gst_pad_new_from_template (templ, name);
- g_free (name);
-
- /* construct our own wrapper data structure for the pad to
- * keep track of its status */
- {
- GstOggPad *oggpad;
-
- oggpad = (GstOggPad *)
- gst_collect_pads_add_pad_full (ogg_mux->collect, newpad,
- sizeof (GstOggPad), gst_ogg_mux_ogg_pad_destroy_notify);
- ogg_mux->active_pads++;
-
- oggpad->serial = serial;
- ogg_stream_init (&oggpad->stream, serial);
- oggpad->packetno = 0;
- oggpad->pageno = 0;
- oggpad->eos = FALSE;
- /* we assume there will be some control data first for this pad */
- oggpad->state = GST_OGG_PAD_STATE_CONTROL;
- oggpad->new_page = TRUE;
- oggpad->first_delta = FALSE;
- oggpad->prev_delta = FALSE;
- oggpad->pagebuffers = g_queue_new ();
- }
- }
-
- /* setup some pad functions */
- gst_pad_set_link_function (newpad, gst_ogg_mux_sinkconnect);
- /* dd the pad to the element */
- gst_element_add_pad (element, newpad);
-
- return newpad;
-
- /* ERRORS */
-wrong_direction:
- {
- g_warning ("ogg_mux: request pad that is not a SINK pad\n");
- return NULL;
- }
-wrong_template:
- {
- g_warning ("ogg_mux: this is not our template!\n");
- return NULL;
- }
-}
-
-static void
-gst_ogg_mux_release_pad (GstElement * element, GstPad * pad)
-{
- GstOggMux *ogg_mux;
-
- ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad));
-
- gst_collect_pads_remove_pad (ogg_mux->collect, pad);
- gst_element_remove_pad (element, pad);
-
- gst_object_unref (ogg_mux);
-}
-
-/* handle events */
-static gboolean
-gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event)
-{
- GstEventType type;
-
- type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
-
- switch (type) {
- case GST_EVENT_SEEK:
- /* disable seeking for now */
- return FALSE;
- default:
- break;
- }
-
- return gst_pad_event_default (pad, event);
-}
-
-static GstBuffer *
-gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta)
-{
- GstBuffer *buffer;
-
- /* allocate space for header and body */
- buffer = gst_buffer_new_and_alloc (page->header_len + page->body_len);
- memcpy (GST_BUFFER_DATA (buffer), page->header, page->header_len);
- memcpy (GST_BUFFER_DATA (buffer) + page->header_len,
- page->body, page->body_len);
-
- /* Here we set granulepos as our OFFSET_END to give easy direct access to
- * this value later. Before we push it, we reset this to OFFSET + SIZE
- * (see gst_ogg_mux_push_buffer). */
- GST_BUFFER_OFFSET_END (buffer) = ogg_page_granulepos (page);
- if (delta)
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
-
- GST_LOG_OBJECT (mux, GST_GP_FORMAT
- " created buffer %p from ogg page", ogg_page_granulepos (page), buffer);
-
- return buffer;
-}
-
-static GstFlowReturn
-gst_ogg_mux_push_buffer (GstOggMux * mux, GstBuffer * buffer)
-{
- GstCaps *caps;
-
- /* fix up OFFSET and OFFSET_END again */
- GST_BUFFER_OFFSET (buffer) = mux->offset;
- mux->offset += GST_BUFFER_SIZE (buffer);
- GST_BUFFER_OFFSET_END (buffer) = mux->offset;
-
- /* Ensure we have monotonically increasing timestamps in the output. */
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
- if (mux->last_ts != GST_CLOCK_TIME_NONE &&
- GST_BUFFER_TIMESTAMP (buffer) < mux->last_ts)
- GST_BUFFER_TIMESTAMP (buffer) = mux->last_ts;
- else
- mux->last_ts = GST_BUFFER_TIMESTAMP (buffer);
- }
-
- caps = gst_pad_get_negotiated_caps (mux->srcpad);
- gst_buffer_set_caps (buffer, caps);
- gst_caps_unref (caps);
-
- return gst_pad_push (mux->srcpad, buffer);
-}
-
-/* if all queues have at least one page, dequeue the page with the lowest
- * timestamp */
-static gboolean
-gst_ogg_mux_dequeue_page (GstOggMux * mux, GstFlowReturn * flowret)
-{
- GSList *walk;
- GstOggPad *opad = NULL; /* "oldest" pad */
- GstClockTime oldest = GST_CLOCK_TIME_NONE;
- GstBuffer *buf = NULL;
- gboolean ret = FALSE;
-
- *flowret = GST_FLOW_OK;
-
- walk = mux->collect->data;
- while (walk) {
- GstOggPad *pad = (GstOggPad *) walk->data;
-
- /* We need each queue to either be at EOS, or have one or more pages
- * available with a set granulepos (i.e. not -1), otherwise we don't have
- * enough data yet to determine which stream needs to go next for correct
- * time ordering. */
- if (pad->pagebuffers->length == 0) {
- if (pad->eos) {
- GST_LOG_OBJECT (pad->collect.pad,
- "pad is EOS, skipping for dequeue decision");
- } else {
- GST_LOG_OBJECT (pad->collect.pad,
- "no pages in this queue, can't dequeue");
- return FALSE;
- }
- } else {
- /* We then need to check for a non-negative granulepos */
- int i;
- gboolean valid = FALSE;
-
- for (i = 0; i < pad->pagebuffers->length; i++) {
- buf = g_queue_peek_nth (pad->pagebuffers, i);
- /* Here we check the OFFSET_END, which is actually temporarily the
- * granulepos value for this buffer */
- if (GST_BUFFER_OFFSET_END (buf) != -1) {
- valid = TRUE;
- break;
- }
- }
- if (!valid) {
- GST_LOG_OBJECT (pad->collect.pad,
- "No page timestamps in queue, can't dequeue");
- return FALSE;
- }
- }
-
- walk = g_slist_next (walk);
- }
-
- walk = mux->collect->data;
- while (walk) {
- GstOggPad *pad = (GstOggPad *) walk->data;
-
- /* any page with a granulepos of -1 can be pushed immediately.
- * TODO: it CAN be, but it seems silly to do so? */
- buf = g_queue_peek_head (pad->pagebuffers);
- while (buf && GST_BUFFER_OFFSET_END (buf) == -1) {
- GST_LOG_OBJECT (pad->collect.pad, "[gp -1] pushing page");
- g_queue_pop_head (pad->pagebuffers);
- *flowret = gst_ogg_mux_push_buffer (mux, buf);
- buf = g_queue_peek_head (pad->pagebuffers);
- ret = TRUE;
- }
-
- if (buf) {
- /* if no oldest buffer yet, take this one */
- if (oldest == GST_CLOCK_TIME_NONE) {
- GST_LOG_OBJECT (mux, "no oldest yet, taking buffer %p from pad %"
- GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT,
- buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
- oldest = GST_BUFFER_OFFSET (buf);
- opad = pad;
- } else {
- /* if we have an oldest, compare with this one */
- if (GST_BUFFER_OFFSET (buf) < oldest) {
- GST_LOG_OBJECT (mux, "older buffer %p, taking from pad %"
- GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT,
- buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
- oldest = GST_BUFFER_OFFSET (buf);
- opad = pad;
- }
- }
- }
- walk = g_slist_next (walk);
- }
-
- if (oldest != GST_CLOCK_TIME_NONE) {
- g_assert (opad);
- buf = g_queue_pop_head (opad->pagebuffers);
- GST_LOG_OBJECT (opad->collect.pad,
- GST_GP_FORMAT " pushing oldest page buffer %p (granulepos time %"
- GST_TIME_FORMAT ")", GST_BUFFER_OFFSET_END (buf), buf,
- GST_TIME_ARGS (GST_BUFFER_OFFSET (buf)));
- *flowret = gst_ogg_mux_push_buffer (mux, buf);
- ret = TRUE;
- }
-
- return ret;
-}
-
-/* put the given ogg page on a per-pad queue, timestamping it correctly.
- * after that, dequeue and push as many pages as possible.
- * Caller should make sure:
- * pad->timestamp was set with the timestamp of the first packet put
- * on the page
- * pad->timestamp_end was set with the timestamp + duration of the last packet
- * put on the page
- * pad->gp_time was set with the time matching the gp of the last
- * packet put on the page
- *
- * will also reset timestamp and timestamp_end, so caller func can restart
- * counting.
- */
-static GstFlowReturn
-gst_ogg_mux_pad_queue_page (GstOggMux * mux, GstOggPad * pad, ogg_page * page,
- gboolean delta)
-{
- GstFlowReturn ret;
- GstBuffer *buffer = gst_ogg_mux_buffer_from_page (mux, page, delta);
-
- /* take the timestamp of the first packet on this page */
- GST_BUFFER_TIMESTAMP (buffer) = pad->timestamp;
- GST_BUFFER_DURATION (buffer) = pad->timestamp_end - pad->timestamp;
- /* take the gp time of the last completed packet on this page */
- GST_BUFFER_OFFSET (buffer) = pad->gp_time;
-
- /* the next page will start where the current page's end time leaves off */
- pad->timestamp = pad->timestamp_end;
-
- g_queue_push_tail (pad->pagebuffers, buffer);
- GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT
- " queued buffer page %p (gp time %"
- GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT
- "), %d page buffers queued", ogg_page_granulepos (page),
- buffer, GST_TIME_ARGS (GST_BUFFER_OFFSET (buffer)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- g_queue_get_length (pad->pagebuffers));
-
- while (gst_ogg_mux_dequeue_page (mux, &ret)) {
- if (ret != GST_FLOW_OK)
- break;
- }
-
- return ret;
-}
-
-/*
- * Given two pads, compare the buffers queued on it.
- * Returns:
- * 0 if they have an equal priority
- * -1 if the first is better
- * 1 if the second is better
- * Priority decided by: a) validity, b) older timestamp, c) smaller number
- * of muxed pages
- */
-static gint
-gst_ogg_mux_compare_pads (GstOggMux * ogg_mux, GstOggPad * first,
- GstOggPad * second)
-{
- guint64 firsttime, secondtime;
-
- /* if the first pad doesn't contain anything or is even NULL, return
- * the second pad as best candidate and vice versa */
- if (first == NULL || (first->buffer == NULL && first->next_buffer == NULL))
- return 1;
- if (second == NULL || (second->buffer == NULL && second->next_buffer == NULL))
- return -1;
-
- /* no timestamp on first buffer, it must go first */
- if (first->buffer)
- firsttime = GST_BUFFER_TIMESTAMP (first->buffer);
- else
- firsttime = GST_BUFFER_TIMESTAMP (first->next_buffer);
- if (firsttime == GST_CLOCK_TIME_NONE)
- return -1;
-
- /* no timestamp on second buffer, it must go first */
- if (second->buffer)
- secondtime = GST_BUFFER_TIMESTAMP (second->buffer);
- else
- secondtime = GST_BUFFER_TIMESTAMP (second->next_buffer);
- if (secondtime == GST_CLOCK_TIME_NONE)
- return 1;
-
- /* first buffer has higher timestamp, second one should go first */
- if (secondtime < firsttime)
- return 1;
- /* second buffer has higher timestamp, first one should go first */
- else if (secondtime > firsttime)
- return -1;
- else {
- /* buffers with equal timestamps, prefer the pad that has the
- * least number of pages muxed */
- if (second->pageno < first->pageno)
- return 1;
- else if (second->pageno > first->pageno)
- return -1;
- }
-
- /* same priority if all of the above failed */
- return 0;
-}
-
-/* make sure at least one buffer is queued on all pads, two if possible
- *
- * if pad->buffer == NULL, pad->next_buffer != NULL, then
- * we do not know if the buffer is the last or not
- * if pad->buffer != NULL, pad->next_buffer != NULL, then
- * pad->buffer is not the last buffer for the pad
- * if pad->buffer != NULL, pad->next_buffer == NULL, then
- * pad->buffer if the last buffer for the pad
- *
- * returns a pointer to an oggpad that holds the best buffer, or
- * NULL when no pad was usable. "best" means the buffer marked
- * with the lowest timestamp. If best->buffer == NULL then nothing
- * should be done until more data arrives */
-static GstOggPad *
-gst_ogg_mux_queue_pads (GstOggMux * ogg_mux)
-{
- GstOggPad *bestpad = NULL, *still_hungry = NULL;
- GSList *walk;
-
- /* try to make sure we have a buffer from each usable pad first */
- walk = ogg_mux->collect->data;
- while (walk) {
- GstOggPad *pad;
- GstCollectData *data;
-
- data = (GstCollectData *) walk->data;
- pad = (GstOggPad *) data;
-
- walk = g_slist_next (walk);
-
- GST_LOG_OBJECT (data->pad, "looking at pad for buffer");
-
- /* try to get a new buffer for this pad if needed and possible */
- if (pad->buffer == NULL) {
- GstBuffer *buf;
- gboolean incaps;
-
- /* shift the buffer along if needed (it's okay if next_buffer is NULL) */
- if (pad->buffer == NULL) {
- GST_LOG_OBJECT (data->pad, "shifting buffer %" GST_PTR_FORMAT,
- pad->next_buffer);
- pad->buffer = pad->next_buffer;
- pad->next_buffer = NULL;
- }
-
- buf = gst_collect_pads_pop (ogg_mux->collect, data);
- GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
-
- /* On EOS we get a NULL buffer */
- if (buf != NULL) {
- if (ogg_mux->delta_pad == NULL &&
- GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT))
- ogg_mux->delta_pad = pad;
-
- incaps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
- /* if we need headers */
- if (pad->state == GST_OGG_PAD_STATE_CONTROL) {
- /* and we have one */
- if (incaps) {
- GST_DEBUG_OBJECT (ogg_mux,
- "got incaps buffer in control state, ignoring");
- /* just ignore */
- gst_buffer_unref (buf);
- buf = NULL;
- } else {
- GST_DEBUG_OBJECT (ogg_mux,
- "got data buffer in control state, switching " "to data mode");
- /* this is a data buffer so switch to data state */
- pad->state = GST_OGG_PAD_STATE_DATA;
- }
- }
- } else {
- GST_DEBUG_OBJECT (data->pad, "EOS on pad");
- if (!pad->eos) {
- ogg_page page;
- GstFlowReturn ret;
-
- /* it's no longer active */
- ogg_mux->active_pads--;
-
- /* Just gone to EOS. Flush existing page(s) */
- pad->eos = TRUE;
-
- while (ogg_stream_flush (&pad->stream, &page)) {
- /* Place page into the per-pad queue */
- ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
- pad->first_delta);
- /* increment the page number counter */
- pad->pageno++;
- /* mark other pages as delta */
- pad->first_delta = TRUE;
- }
- }
- }
-
- pad->next_buffer = buf;
- }
-
- /* we should have a buffer now, see if it is the best pad to
- * pull on */
- if (pad->buffer || pad->next_buffer) {
- if (gst_ogg_mux_compare_pads (ogg_mux, bestpad, pad) > 0) {
- GST_LOG_OBJECT (data->pad,
- "new best pad, with buffers %" GST_PTR_FORMAT
- " and %" GST_PTR_FORMAT, pad->buffer, pad->next_buffer);
-
- bestpad = pad;
- }
- } else if (!pad->eos) {
- GST_LOG_OBJECT (data->pad, "hungry pad");
- still_hungry = pad;
- }
- }
-
- if (still_hungry)
- /* drop back into collectpads... */
- return still_hungry;
- else
- return bestpad;
-}
-
-static GList *
-gst_ogg_mux_get_headers (GstOggPad * pad)
-{
- GList *res = NULL;
- GstOggMux *ogg_mux;
- GstStructure *structure;
- GstCaps *caps;
- GstPad *thepad;
-
- thepad = pad->collect.pad;
-
- ogg_mux = GST_OGG_MUX (GST_PAD_PARENT (thepad));
-
- GST_LOG_OBJECT (thepad, "getting headers");
-
- caps = gst_pad_get_negotiated_caps (thepad);
- if (caps != NULL) {
- const GValue *streamheader;
-
- structure = gst_caps_get_structure (caps, 0);
- if (strcmp (gst_structure_get_name (structure), "video/x-dirac") == 0) {
- GstBuffer *buf = gst_buffer_new_and_alloc (16);
- int fps_n = 12;
- int fps_d = 1;
-
- gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
-
- memcpy (GST_BUFFER_DATA (buf), "KW-DIRAC", 8);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, fps_n);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 12, fps_d);
-
- res = g_list_append (res, buf);
-
- //res = g_list_append (res, gst_buffer_ref(pad->buffer));
- } else {
- streamheader = gst_structure_get_value (structure, "streamheader");
- if (streamheader != NULL) {
- GST_LOG_OBJECT (thepad, "got header");
- if (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) {
- GArray *bufarr = g_value_peek_pointer (streamheader);
- gint i;
-
- GST_LOG_OBJECT (thepad, "got fixed list");
-
- for (i = 0; i < bufarr->len; i++) {
- GValue *bufval = &g_array_index (bufarr, GValue, i);
-
- GST_LOG_OBJECT (thepad, "item %d", i);
- if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) {
- GstBuffer *buf = g_value_peek_pointer (bufval);
-
- GST_LOG_OBJECT (thepad, "adding item %d to header list", i);
-
- gst_buffer_ref (buf);
- res = g_list_append (res, buf);
- }
- }
- } else {
- GST_LOG_OBJECT (thepad, "streamheader is not fixed list");
- }
- } else {
- GST_LOG_OBJECT (thepad, "caps don't have streamheader");
- }
- }
- gst_caps_unref (caps);
- } else {
- GST_LOG_OBJECT (thepad, "got empty caps as negotiated format");
- }
- return res;
-}
-
-static GstCaps *
-gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers)
-{
- GstStructure *structure;
- GValue array = { 0 };
- GList *walk = buffers;
-
- caps = gst_caps_make_writable (caps);
-
- structure = gst_caps_get_structure (caps, 0);
-
- /* put buffers in a fixed list */
- g_value_init (&array, GST_TYPE_ARRAY);
-
- while (walk) {
- GstBuffer *buf = GST_BUFFER (walk->data);
- GstBuffer *copy;
- GValue value = { 0 };
-
- walk = walk->next;
-
- /* mark buffer */
- GST_LOG ("Setting IN_CAPS on buffer of length %d", GST_BUFFER_SIZE (buf));
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- copy = gst_buffer_copy (buf);
- gst_value_set_buffer (&value, copy);
- gst_buffer_unref (copy);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- }
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&array);
-
- return caps;
-}
-
-/*
- * For each pad we need to write out one (small) header in one
- * page that allows decoders to identify the type of the stream.
- * After that we need to write out all extra info for the decoders.
- * In the case of a codec that also needs data as configuration, we can
- * find that info in the streamcaps.
- * After writing the headers we must start a new page for the data.
- */
-static GstFlowReturn
-gst_ogg_mux_send_headers (GstOggMux * mux)
-{
- GSList *walk;
- GList *hbufs, *hwalk;
- GstCaps *caps;
- GstFlowReturn ret;
-
- hbufs = NULL;
- ret = GST_FLOW_OK;
-
- GST_LOG_OBJECT (mux, "collecting headers");
-
- walk = mux->collect->data;
- while (walk) {
- GstOggPad *pad;
- GstPad *thepad;
-
- pad = (GstOggPad *) walk->data;
- thepad = pad->collect.pad;
-
- walk = g_slist_next (walk);
-
- GST_LOG_OBJECT (mux, "looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
-
- /* if the pad has no buffer, we don't care */
- if (pad->buffer == NULL && pad->next_buffer == NULL)
- continue;
-
- /* now figure out the headers */
- pad->headers = gst_ogg_mux_get_headers (pad);
- }
-
- GST_LOG_OBJECT (mux, "creating BOS pages");
- walk = mux->collect->data;
- while (walk) {
- GstOggPad *pad;
- GstBuffer *buf;
- ogg_packet packet;
- ogg_page page;
- GstPad *thepad;
- GstCaps *caps;
- GstStructure *structure;
- GstBuffer *hbuf;
-
- pad = (GstOggPad *) walk->data;
- thepad = pad->collect.pad;
- caps = gst_pad_get_negotiated_caps (thepad);
- structure = gst_caps_get_structure (caps, 0);
-
- walk = walk->next;
-
- pad->packetno = 0;
-
- GST_LOG_OBJECT (thepad, "looping over headers");
-
- if (pad->headers) {
- buf = GST_BUFFER (pad->headers->data);
- pad->headers = g_list_remove (pad->headers, buf);
- } else if (pad->buffer) {
- buf = pad->buffer;
- gst_buffer_ref (buf);
- } else if (pad->next_buffer) {
- buf = pad->next_buffer;
- gst_buffer_ref (buf);
- } else {
- /* fixme -- should be caught in the previous list traversal. */
- GST_OBJECT_LOCK (pad);
- g_critical ("No headers or buffers on pad %s:%s",
- GST_DEBUG_PAD_NAME (pad));
- GST_OBJECT_UNLOCK (pad);
- continue;
- }
-
- /* create a packet from the buffer */
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- if (packet.granulepos == -1)
- packet.granulepos = 0;
- /* mark BOS and packet number */
- packet.b_o_s = (pad->packetno == 0);
- packet.packetno = pad->packetno++;
- /* mark EOS */
- packet.e_o_s = 0;
-
- /* swap the packet in */
- ogg_stream_packetin (&pad->stream, &packet);
- gst_buffer_unref (buf);
-
- GST_LOG_OBJECT (thepad, "flushing out BOS page");
- if (!ogg_stream_flush (&pad->stream, &page))
- g_critical ("Could not flush BOS page");
-
- hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
- GST_LOG_OBJECT (mux, "swapped out page with mime type %s",
- gst_structure_get_name (structure));
-
- /* quick hack: put Theora and Dirac video pages at the front.
- * Ideally, we would have a settable enum for which Ogg
- * profile we work with, and order based on that.
- * (FIXME: if there is more than one video stream, shouldn't we only put
- * one's BOS into the first page, followed by an audio stream's BOS, and
- * only then followed by the remaining video and audio streams?) */
- if (gst_structure_has_name (structure, "video/x-theora")) {
- GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Theora");
- hbufs = g_list_prepend (hbufs, hbuf);
- } else if (gst_structure_has_name (structure, "video/x-dirac")) {
- GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Dirac");
- hbufs = g_list_prepend (hbufs, hbuf);
- } else {
- hbufs = g_list_append (hbufs, hbuf);
- }
- gst_caps_unref (caps);
- }
-
- GST_LOG_OBJECT (mux, "creating next headers");
- walk = mux->collect->data;
- while (walk) {
- GstOggPad *pad;
- GstPad *thepad;
-
- pad = (GstOggPad *) walk->data;
- thepad = pad->collect.pad;
-
- walk = walk->next;
-
- GST_LOG_OBJECT (mux, "looping over headers for pad %s:%s",
- GST_DEBUG_PAD_NAME (thepad));
-
- hwalk = pad->headers;
- while (hwalk) {
- GstBuffer *buf = GST_BUFFER (hwalk->data);
- ogg_packet packet;
- ogg_page page;
-
- hwalk = hwalk->next;
-
- /* create a packet from the buffer */
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- if (packet.granulepos == -1)
- packet.granulepos = 0;
- /* mark BOS and packet number */
- packet.b_o_s = (pad->packetno == 0);
- packet.packetno = pad->packetno++;
- /* mark EOS */
- packet.e_o_s = 0;
-
- /* swap the packet in */
- ogg_stream_packetin (&pad->stream, &packet);
- gst_buffer_unref (buf);
-
- /* if last header, flush page */
- if (hwalk == NULL) {
- GST_LOG_OBJECT (mux,
- "flushing page as packet %" G_GUINT64_FORMAT " is first or "
- "last packet", pad->packetno);
- while (ogg_stream_flush (&pad->stream, &page)) {
- GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
- GST_LOG_OBJECT (mux, "swapped out page");
- hbufs = g_list_append (hbufs, hbuf);
- }
- } else {
- GST_LOG_OBJECT (mux, "try to swap out page");
- /* just try to swap out a page then */
- while (ogg_stream_pageout (&pad->stream, &page) > 0) {
- GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE);
-
- GST_LOG_OBJECT (mux, "swapped out page");
- hbufs = g_list_append (hbufs, hbuf);
- }
- }
- }
- g_list_free (pad->headers);
- pad->headers = NULL;
- }
- /* hbufs holds all buffers for the headers now */
-
- /* create caps with the buffers */
- caps = gst_pad_get_caps (mux->srcpad);
- if (caps) {
- caps = gst_ogg_mux_set_header_on_caps (caps, hbufs);
- gst_pad_set_caps (mux->srcpad, caps);
- gst_caps_unref (caps);
- }
- /* and send the buffers */
- hwalk = hbufs;
- while (hwalk) {
- GstBuffer *buf = GST_BUFFER (hwalk->data);
-
- hwalk = hwalk->next;
-
- if ((ret = gst_ogg_mux_push_buffer (mux, buf)) != GST_FLOW_OK)
- break;
- }
- g_list_free (hbufs);
-
- return ret;
-}
-
-/* this function is called to process data on the best pending pad.
- *
- * basic idea:
- *
- * 1) store the selected pad and keep on pulling until we fill a
- * complete ogg page or the ogg page is filled above the max-delay
- * threshold. This is needed because the ogg spec says that
- * you should fill a complete page with data from the same logical
- * stream. When the page is filled, go back to 1).
- * 2) before filling a page, read ahead one more buffer to see if this
- * packet is the last of the stream. We need to do this because the ogg
- * spec mandates that the last packet should have the EOS flag set before
- * sending it to ogg. if pad->buffer is NULL we need to wait to find out
- * whether there are any more buffers.
- * 3) pages get queued on a per-pad queue. Every time a page is queued, a
- * dequeue is called, which will dequeue the oldest page on any pad, provided
- * that ALL pads have at least one marked page in the queue (or remaining
- * pads are at EOS)
- */
-static GstFlowReturn
-gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPad * best)
-{
- gboolean delta_unit;
- GstFlowReturn ret;
- gint64 granulepos = 0;
- GstClockTime timestamp, gp_time;
-
- GST_LOG_OBJECT (ogg_mux, "best pad %" GST_PTR_FORMAT
- ", currently pulling from %" GST_PTR_FORMAT, best->collect.pad,
- ogg_mux->pulling);
-
- /* best->buffer is non-NULL, either the pad is EOS's or there is a next
- * buffer */
- if (best->next_buffer == NULL && !best->eos) {
- GST_WARNING_OBJECT (ogg_mux, "no subsequent buffer and EOS not reached");
- return GST_FLOW_WRONG_STATE;
- }
-
- /* if we were already pulling from one pad, but the new "best" buffer is
- * from another pad, we need to check if we have reason to flush a page
- * for the pad we were pulling from before */
- if (ogg_mux->pulling && best &&
- ogg_mux->pulling != best && ogg_mux->pulling->buffer) {
- GstOggPad *pad = ogg_mux->pulling;
-
- GstClockTime last_ts = GST_BUFFER_END_TIME (pad->buffer);
-
- /* if the next packet in the current page is going to make the page
- * too long, we need to flush */
- if (last_ts > ogg_mux->next_ts + ogg_mux->max_delay) {
- ogg_page page;
-
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT " stored packet %" G_GINT64_FORMAT
- " will make page too long, flushing",
- GST_BUFFER_OFFSET_END (pad->buffer), pad->stream.packetno);
-
- while (ogg_stream_flush (&pad->stream, &page)) {
- /* end time of this page is the timestamp of the next buffer */
- ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
- /* Place page into the per-pad queue */
- ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
- pad->first_delta);
- /* increment the page number counter */
- pad->pageno++;
- /* mark other pages as delta */
- pad->first_delta = TRUE;
- }
- pad->new_page = TRUE;
- ogg_mux->pulling = NULL;
- }
- }
-
- /* if we don't know which pad to pull on, use the best one */
- if (ogg_mux->pulling == NULL) {
- ogg_mux->pulling = best;
- GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from best pad");
-
- /* remember timestamp and gp time of first buffer for this new pad */
- if (ogg_mux->pulling != NULL) {
- ogg_mux->next_ts = GST_BUFFER_TIMESTAMP (ogg_mux->pulling->buffer);
- GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "updated times, next ts %"
- GST_TIME_FORMAT, GST_TIME_ARGS (ogg_mux->next_ts));
- } else {
- /* no pad to pull on, send EOS */
- gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
- return GST_FLOW_WRONG_STATE;
- }
- }
-
- if (ogg_mux->need_headers) {
- ret = gst_ogg_mux_send_headers (ogg_mux);
- ogg_mux->need_headers = FALSE;
- }
-
- /* we are pulling from a pad, continue to do so until a page
- * has been filled and queued */
- if (ogg_mux->pulling != NULL) {
- ogg_packet packet;
- ogg_page page;
- GstBuffer *buf, *tmpbuf;
- GstOggPad *pad = ogg_mux->pulling;
- gint64 duration;
- gboolean force_flush;
-
- GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from pad");
-
- /* now see if we have a buffer */
- buf = pad->buffer;
- if (buf == NULL) {
- GST_DEBUG_OBJECT (ogg_mux, "pad was EOS");
- ogg_mux->pulling = NULL;
- return GST_FLOW_OK;
- }
-
- delta_unit = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
- duration = GST_BUFFER_DURATION (buf);
-
- /* if the current "next timestamp" on the pad is unset, then this is the
- * first packet on the new page. Update our pad's page timestamp */
- if (ogg_mux->pulling->timestamp == GST_CLOCK_TIME_NONE) {
- ogg_mux->pulling->timestamp = GST_BUFFER_TIMESTAMP (buf);
- GST_LOG_OBJECT (ogg_mux->pulling->collect.pad,
- "updated pad timestamp to %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
- }
- /* create a packet from the buffer */
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- if (packet.granulepos == -1)
- packet.granulepos = 0;
- /* mark BOS and packet number */
- packet.b_o_s = (pad->packetno == 0);
- packet.packetno = pad->packetno++;
- GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT
- " packet %" G_GINT64_FORMAT " (%ld bytes) created from buffer",
- packet.granulepos, packet.packetno, packet.bytes);
-
- packet.e_o_s = (pad->eos ? 1 : 0);
- tmpbuf = NULL;
-
- /* we flush when we see a new keyframe */
- force_flush = (pad->prev_delta && !delta_unit);
- if (duration != -1) {
- pad->duration += duration;
- /* if page duration exceeds max, flush page */
- if (pad->duration > ogg_mux->max_page_delay) {
- force_flush = TRUE;
- pad->duration = 0;
- }
- }
-
- if (GST_BUFFER_IS_DISCONT (buf)) {
- packet.packetno++;
- /* No public API for this; hack things in */
- pad->stream.pageno++;
- force_flush = TRUE;
- }
-
- /* flush the currently built page if necessary */
- if (force_flush) {
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT " forced flush of page before this packet",
- GST_BUFFER_OFFSET_END (pad->buffer));
- while (ogg_stream_flush (&pad->stream, &page)) {
- /* end time of this page is the timestamp of the next buffer */
- ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer);
- ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
- pad->first_delta);
-
- /* increment the page number counter */
- pad->pageno++;
- /* mark other pages as delta */
- pad->first_delta = TRUE;
- }
- pad->new_page = TRUE;
- }
-
- /* if this is the first packet of a new page figure out the delta flag */
- if (pad->new_page) {
- if (delta_unit) {
- /* mark the page as delta */
- pad->first_delta = TRUE;
- } else {
- /* got a keyframe */
- if (ogg_mux->delta_pad == pad) {
- /* if we get it on the pad with deltaunits,
- * we mark the page as non delta */
- pad->first_delta = FALSE;
- } else if (ogg_mux->delta_pad != NULL) {
- /* if there are pads with delta frames, we
- * must mark this one as delta */
- pad->first_delta = TRUE;
- } else {
- pad->first_delta = FALSE;
- }
- }
- pad->new_page = FALSE;
- }
-
- /* save key unit to track delta->key unit transitions */
- pad->prev_delta = delta_unit;
-
- /* swap the packet in */
- if (packet.e_o_s == 1)
- GST_DEBUG_OBJECT (pad->collect.pad, "swapping in EOS packet");
- if (packet.b_o_s == 1)
- GST_DEBUG_OBJECT (pad->collect.pad, "swapping in BOS packet");
-
- ogg_stream_packetin (&pad->stream, &packet);
-
- gp_time = GST_BUFFER_OFFSET (pad->buffer);
- granulepos = GST_BUFFER_OFFSET_END (pad->buffer);
- timestamp = GST_BUFFER_TIMESTAMP (pad->buffer);
-
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", gp time %"
- GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT " packetin'd",
- granulepos, packet.packetno, GST_TIME_ARGS (gp_time),
- GST_TIME_ARGS (timestamp));
- /* don't need the old buffer anymore */
- gst_buffer_unref (pad->buffer);
- /* store new readahead buffer */
- pad->buffer = tmpbuf;
-
- /* let ogg write out the pages now. The packet we got could end
- * up in more than one page so we need to write them all */
- if (ogg_stream_pageout (&pad->stream, &page) > 0) {
- /* we have a new page, so we need to timestamp it correctly.
- * if this fresh packet ends on this page, then the page's granulepos
- * comes from that packet, and we should set this buffer's timestamp */
-
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", time %"
- GST_TIME_FORMAT ") caused new page",
- granulepos, packet.packetno, GST_TIME_ARGS (timestamp));
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT " new page %ld", ogg_page_granulepos (&page),
- pad->stream.pageno);
-
- if (ogg_page_granulepos (&page) == granulepos) {
- /* the packet we streamed in finishes on the current page,
- * because the page's granulepos is the granulepos of the last
- * packet completed on that page,
- * so update the timestamp that we will give to the page */
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT
- " packet finishes on current page, updating gp time to %"
- GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (gp_time));
- pad->gp_time = gp_time;
- } else {
- GST_LOG_OBJECT (pad->collect.pad,
- GST_GP_FORMAT
- " packet spans beyond current page, keeping old gp time %"
- GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (pad->gp_time));
- }
-
- /* push the page */
- /* end time of this page is the timestamp of the next buffer */
- pad->timestamp_end = timestamp;
- ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, pad->first_delta);
- pad->pageno++;
- /* mark next pages as delta */
- pad->first_delta = TRUE;
-
- /* use an inner loop here to flush the remaining pages and
- * mark them as delta frames as well */
- while (ogg_stream_pageout (&pad->stream, &page) > 0) {
- if (ogg_page_granulepos (&page) == granulepos) {
- /* the page has taken up the new packet completely, which means
- * the packet ends the page and we can update the gp time
- * before pushing out */
- pad->gp_time = gp_time;
- }
-
- /* we have a complete page now, we can push the page
- * and make sure to pull on a new pad the next time around */
- ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page,
- pad->first_delta);
- /* increment the page number counter */
- pad->pageno++;
- }
- /* need a new page as well */
- pad->new_page = TRUE;
- pad->duration = 0;
- /* we're done pulling on this pad, make sure to choose a new
- * pad for pulling in the next iteration */
- ogg_mux->pulling = NULL;
- }
-
- /* Update the gp time, if necessary, since any future page will have at
- * least this gp time.
- */
- if (pad->gp_time < gp_time) {
- pad->gp_time = gp_time;
- GST_LOG_OBJECT (pad->collect.pad,
- "Updated running gp time of pad %" GST_PTR_FORMAT
- " to %" GST_TIME_FORMAT, pad->collect.pad, GST_TIME_ARGS (gp_time));
- }
- }
-
- return GST_FLOW_OK;
-}
-
-/** all_pads_eos:
- *
- * Checks if all pads are EOS'd by peeking.
- *
- * Returns TRUE if all pads are EOS.
- */
-static gboolean
-all_pads_eos (GstCollectPads * pads)
-{
- GSList *walk;
- gboolean alleos = TRUE;
-
- walk = pads->data;
- while (walk) {
- GstBuffer *buf;
- GstCollectData *data = (GstCollectData *) walk->data;
-
- buf = gst_collect_pads_peek (pads, data);
- if (buf) {
- alleos = FALSE;
- gst_buffer_unref (buf);
- goto beach;
- }
- walk = walk->next;
- }
-beach:
- return alleos;
-}
-
-/* This function is called when there is data on all pads.
- *
- * It finds a pad to pull on, this is done by looking at the buffers
- * to decide which one to use, and using the 'oldest' one first. It then calls
- * gst_ogg_mux_process_best_pad() to process as much data as possible.
- *
- * If all the pads have received EOS, it flushes out all data by continually
- * getting the best pad and calling gst_ogg_mux_process_best_pad() until they
- * are all empty, and then sends EOS.
- */
-static GstFlowReturn
-gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux)
-{
- GstOggPad *best;
- GstFlowReturn ret;
- gint activebefore;
-
- GST_LOG_OBJECT (ogg_mux, "collected");
-
- activebefore = ogg_mux->active_pads;
-
- /* queue buffers on all pads; find a buffer with the lowest timestamp */
- best = gst_ogg_mux_queue_pads (ogg_mux);
- if (best && !best->buffer) {
- GST_DEBUG_OBJECT (ogg_mux, "No buffer available on best pad");
- return GST_FLOW_OK;
- }
-
- if (!best) {
- return GST_FLOW_WRONG_STATE;
- }
-
- ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
-
- if (ogg_mux->active_pads < activebefore) {
- /* If the active pad count went down, this mean at least one pad has gone
- * EOS. Since CollectPads only calls _collected() once when all pads are
- * EOS, and our code doesn't _pop() from all pads we need to check that by
- * peeking on all pads, else we won't be called again and the muxing will
- * not terminate (push out EOS). */
-
- /* if all the pads have been removed, flush all pending data */
- if ((ret == GST_FLOW_OK) && all_pads_eos (pads)) {
- GST_LOG_OBJECT (ogg_mux, "no pads remaining, flushing data");
-
- do {
- best = gst_ogg_mux_queue_pads (ogg_mux);
- if (best)
- ret = gst_ogg_mux_process_best_pad (ogg_mux, best);
- } while ((ret == GST_FLOW_OK) && (best != NULL));
-
- GST_DEBUG_OBJECT (ogg_mux, "Pushing EOS");
- gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ());
- }
- }
-
- return ret;
-}
-
-static void
-gst_ogg_mux_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstOggMux *ogg_mux;
-
- ogg_mux = GST_OGG_MUX (object);
-
- switch (prop_id) {
- case ARG_MAX_DELAY:
- g_value_set_uint64 (value, ogg_mux->max_delay);
- break;
- case ARG_MAX_PAGE_DELAY:
- g_value_set_uint64 (value, ogg_mux->max_page_delay);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_ogg_mux_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstOggMux *ogg_mux;
-
- ogg_mux = GST_OGG_MUX (object);
-
- switch (prop_id) {
- case ARG_MAX_DELAY:
- ogg_mux->max_delay = g_value_get_uint64 (value);
- break;
- case ARG_MAX_PAGE_DELAY:
- ogg_mux->max_page_delay = g_value_get_uint64 (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* reset all variables in the ogg pads. */
-static void
-gst_ogg_mux_init_collectpads (GstCollectPads * collect)
-{
- GSList *walk;
-
- walk = collect->data;
- while (walk) {
- GstOggPad *oggpad = (GstOggPad *) walk->data;
-
- ogg_stream_init (&oggpad->stream, oggpad->serial);
- oggpad->packetno = 0;
- oggpad->pageno = 0;
- oggpad->eos = FALSE;
- /* we assume there will be some control data first for this pad */
- oggpad->state = GST_OGG_PAD_STATE_CONTROL;
- oggpad->new_page = TRUE;
- oggpad->first_delta = FALSE;
- oggpad->prev_delta = FALSE;
- oggpad->pagebuffers = g_queue_new ();
-
- walk = g_slist_next (walk);
- }
-}
-
-/* Clear all buffers from the collectpads object */
-static void
-gst_ogg_mux_clear_collectpads (GstCollectPads * collect)
-{
- GSList *walk;
-
- for (walk = collect->data; walk; walk = g_slist_next (walk)) {
- GstOggPad *oggpad = (GstOggPad *) walk->data;
- GstBuffer *buf;
-
- ogg_stream_clear (&oggpad->stream);
-
- while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) {
- gst_buffer_unref (buf);
- }
- g_queue_free (oggpad->pagebuffers);
- oggpad->pagebuffers = NULL;
- }
-}
-
-static GstStateChangeReturn
-gst_ogg_mux_change_state (GstElement * element, GstStateChange transition)
-{
- GstOggMux *ogg_mux;
- GstStateChangeReturn ret;
-
- ogg_mux = GST_OGG_MUX (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_ogg_mux_clear (ogg_mux);
- gst_ogg_mux_init_collectpads (ogg_mux->collect);
- gst_collect_pads_start (ogg_mux->collect);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (ogg_mux->collect);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_ogg_mux_clear_collectpads (ogg_mux->collect);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-gboolean
-gst_ogg_mux_plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_ogg_mux_debug, "oggmux", 0, "ogg muxer");
-
- return gst_element_register (plugin, "oggmux", GST_RANK_NONE,
- GST_TYPE_OGG_MUX);
-}
--- a/gst_plugins_base/ext/ogg/gstoggmux.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/* OGG muxer plugin for GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
- * Copyright (C) 2006 Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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 __GST_OGG_MUX_H__
-#define __GST_OGGEMUX_H__
-
-#include <ogg/ogg.h>
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_OGG_MUX (gst_ogg_mux_get_type())
-#define GST_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_MUX, GstOggMux))
-#define GST_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_MUX, GstOggMux))
-#define GST_IS_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_MUX))
-#define GST_IS_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_MUX))
-
-typedef struct _GstOggMux GstOggMux;
-typedef struct _GstOggMuxClass GstOggMuxClass;
-
-typedef enum
-{
- GST_OGG_PAD_STATE_CONTROL = 0,
- GST_OGG_PAD_STATE_DATA = 1
-}
-GstOggPadState;
-
-/* all information needed for one ogg stream */
-typedef struct
-{
- GstCollectData collect; /* we extend the CollectData */
-
- /* These two buffers make a very simple queue - they enter as 'next_buffer'
- * and (usually) leave as 'buffer', except at EOS, when buffer will be NULL */
- GstBuffer *buffer; /* the first waiting buffer for the pad */
- GstBuffer *next_buffer; /* the second waiting buffer for the pad */
-
- gint serial;
- ogg_stream_state stream;
- gint64 packetno; /* number of next packet */
- gint64 pageno; /* number of next page */
- guint64 duration; /* duration of current page */
- gboolean eos;
- gint64 offset;
- GstClockTime timestamp; /* timestamp of the first packet on the next
- * page to be dequeued */
- GstClockTime timestamp_end; /* end timestamp of last complete packet on
- the next page to be dequeued */
- GstClockTime gp_time; /* time corresponding to the gp value of the
- last complete packet on the next page to be
- dequeued */
-
- GstOggPadState state; /* state of the pad */
-
- GList *headers;
-
- GQueue *pagebuffers; /* List of pages in buffers ready for pushing */
-
- gboolean new_page; /* starting a new page */
- gboolean first_delta; /* was the first packet in the page a delta */
- gboolean prev_delta; /* was the previous buffer a delta frame */
-}
-GstOggPad;
-
-struct _GstOggMux
-{
- GstElement element;
-
- /* source pad */
- GstPad *srcpad;
-
- /* sinkpads */
- GstCollectPads *collect;
-
- /* number of pads which have not received EOS */
- gint active_pads;
-
- /* the pad we are currently using to fill a page */
- GstOggPad *pulling;
-
- /* next timestamp for the page */
- GstClockTime next_ts;
-
- /* Last timestamp actually output on src pad */
- GstClockTime last_ts;
-
- /* offset in stream */
- guint64 offset;
-
- /* need_headers */
- gboolean need_headers;
-
- guint64 max_delay;
- guint64 max_page_delay;
-
- GstOggPad *delta_pad; /* when a delta frame is detected on a stream, we mark
- pages as delta frames up to the page that has the
- keyframe */
-
-};
-
-struct _GstOggMuxClass
-{
- GstElementClass parent_class;
-};
-
-GType gst_ogg_mux_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_OGG_MUX_H__ */
--- a/gst_plugins_base/ext/ogg/gstoggparse.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,695 +0,0 @@
-/* GStreamer
- * Copyright (C) 2005 Michael Smith <msmith@fluendo.com>
- *
- * gstoggparse.c: ogg stream parser
- *
- * 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.
- */
-
-/* This ogg parser is essentially a subset of the ogg demuxer - rather than
- * fully demuxing into packets, we only parse out the pages, create one
- * GstBuffer per page, set all the appropriate flags on those pages, set caps
- * appropriately (particularly the 'streamheader' which gives all the header
- * pages required for initialing decode).
- *
- * It's dramatically simpler than the full demuxer as it does not support
- * seeking.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <gst/gst.h>
-#include <ogg/ogg.h>
-#include <string.h>
-
-static const GstElementDetails gst_ogg_parse_details =
-GST_ELEMENT_DETAILS ("Ogg parser",
- "Codec/Parser",
- "parse ogg streams into pages (info about ogg: http://xiph.org)",
- "Michael Smith <msmith@fluendo.com>");
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogg_parse_debug);
-#define GST_CAT_DEFAULT gst_ogg_parse_debug
-
-#define GST_TYPE_OGG_PARSE (gst_ogg_parse_get_type())
-#define GST_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PARSE, GstOggParse))
-#define GST_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PARSE, GstOggParse))
-#define GST_IS_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PARSE))
-#define GST_IS_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PARSE))
-
-static GType gst_ogg_parse_get_type (void);
-
-typedef struct _GstOggParse GstOggParse;
-typedef struct _GstOggParseClass GstOggParseClass;
-
-/* Each ogg logical stream has a GstOggStream associated with it */
-typedef struct
-{
- /*ogg_stream_state stream; *//* We need this to get the packets out in order
- to do codec identification, for various
- codec-specific tasks */
-
- gboolean in_headers; /* Initially true, false once we've read all the
- headers for this logical stream */
-
- guint32 serialno; /* Unique serial number of this stream */
-
- GSList *headers; /* List of ogg pages that we'll set on caps */
- GSList *unknown_pages; /* List of pages we haven't yet classified */
-} GstOggStream;
-
-struct _GstOggParse
-{
- GstElement element;
-
- GstPad *sinkpad; /* Sink pad we're reading data from */
-
- GstPad *srcpad; /* Source pad we're writing to */
-
- GSList *oggstreams; /* list of GstOggStreams for known streams */
-
- gint64 offset; /* Current stream offset */
-
- gboolean in_headers; /* Set if we're reading headers for streams */
-
- gboolean last_page_not_bos; /* Set if we've seen a non-BOS page */
-
- ogg_sync_state sync; /* Ogg page synchronisation */
-
- GstCaps *caps; /* Our src caps */
-};
-
-struct _GstOggParseClass
-{
- GstElementClass parent_class;
-};
-
-static void gst_ogg_parse_base_init (gpointer g_class);
-static void gst_ogg_parse_class_init (GstOggParseClass * klass);
-static void gst_ogg_parse_init (GstOggParse * ogg);
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogg_parse_get_type (void)
-{
- static GType ogg_parse_type = 0;
-
- if (!ogg_parse_type) {
- static const GTypeInfo ogg_parse_info = {
- sizeof (GstOggParseClass),
- gst_ogg_parse_base_init,
- NULL,
- (GClassInitFunc) gst_ogg_parse_class_init,
- NULL,
- NULL,
- sizeof (GstOggParse),
- 0,
- (GInstanceInitFunc) gst_ogg_parse_init,
- };
-
- ogg_parse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOggParse",
- &ogg_parse_info, 0);
- }
- return ogg_parse_type;
-}
-
-static void
-free_stream (GstOggStream * stream)
-{
- g_slist_foreach (stream->headers, (GFunc) gst_mini_object_unref, NULL);
- g_slist_foreach (stream->unknown_pages, (GFunc) gst_mini_object_unref, NULL);
-
- g_free (stream);
-}
-
-static void
-gst_ogg_parse_delete_all_streams (GstOggParse * ogg)
-{
- g_slist_foreach (ogg->oggstreams, (GFunc) free_stream, NULL);
- g_slist_free (ogg->oggstreams);
- ogg->oggstreams = NULL;
-}
-
-static GstOggStream *
-gst_ogg_parse_new_stream (GstOggParse * parser, guint32 serialno)
-{
- GstOggStream *ret;
-
- GST_DEBUG_OBJECT (parser, "creating new stream %08x", serialno);
-
- ret = g_new0 (GstOggStream, 1);
-
- ret->serialno = serialno;
- ret->in_headers = 1;
-
- /*
- if (ogg_stream_init (&ret->stream, serialno) != 0) {
- GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.",
- serialno);
- return NULL;
- }
- */
-
- parser->oggstreams = g_slist_append (parser->oggstreams, ret);
-
- return ret;
-}
-
-static GstOggStream *
-gst_ogg_parse_find_stream (GstOggParse * parser, guint32 serialno)
-{
- GSList *l;
-
- for (l = parser->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
-
- if (stream->serialno == serialno)
- return stream;
- }
- return NULL;
-}
-
-/* signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0
- /* FILL ME */
-};
-
-static GstStaticPadTemplate ogg_parse_src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/ogg")
- );
-
-static GstStaticPadTemplate ogg_parse_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/ogg")
- );
-
-static void gst_ogg_parse_dispose (GObject * object);
-static GstStateChangeReturn gst_ogg_parse_change_state (GstElement * element,
- GstStateChange transition);
-static GstFlowReturn gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer);
-
-static void
-gst_ogg_parse_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_ogg_parse_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_parse_sink_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&ogg_parse_src_template_factory));
-}
-
-static void
-gst_ogg_parse_class_init (GstOggParseClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gstelement_class->change_state = gst_ogg_parse_change_state;
-
- gobject_class->dispose = gst_ogg_parse_dispose;
-}
-
-static void
-gst_ogg_parse_init (GstOggParse * ogg)
-{
- /* create the sink and source pads */
- ogg->sinkpad =
- gst_pad_new_from_static_template (&ogg_parse_sink_template_factory,
- "sink");
- ogg->srcpad =
- gst_pad_new_from_static_template (&ogg_parse_src_template_factory, "src");
-
- /* TODO: Are there any events we must handle? */
- /* gst_pad_set_event_function (ogg->sinkpad, gst_ogg_parse_handle_event); */
- gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_parse_chain);
-
- gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad);
- gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad);
-
- ogg->oggstreams = NULL;
-}
-
-static void
-gst_ogg_parse_dispose (GObject * object)
-{
- GstOggParse *ogg = GST_OGG_PARSE (object);
-
- GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg);
-
- ogg_sync_clear (&ogg->sync);
- gst_ogg_parse_delete_all_streams (ogg);
-
- if (ogg->caps) {
- gst_caps_unref (ogg->caps);
- ogg->caps = NULL;
- }
-
- if (G_OBJECT_CLASS (parent_class)->dispose)
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-/* submit the given buffer to the ogg sync.
- *
- * Returns the number of bytes submited.
- */
-static gint
-gst_ogg_parse_submit_buffer (GstOggParse * ogg, GstBuffer * buffer)
-{
- guint size;
- guint8 *data;
- gchar *oggbuffer;
-
- size = GST_BUFFER_SIZE (buffer);
- data = GST_BUFFER_DATA (buffer);
-
- /* We now have a buffer, submit it to the ogg sync layer */
- oggbuffer = ogg_sync_buffer (&ogg->sync, size);
- memcpy (oggbuffer, data, size);
- ogg_sync_wrote (&ogg->sync, size);
-
- /* We've copied all the neccesary data, so we're done with the buffer */
- gst_buffer_unref (buffer);
-
- return size;
-}
-
-static void
-gst_ogg_parse_append_header (GValue * array, GstBuffer * buf)
-{
- GValue value = { 0 };
- /* We require a copy to avoid circular refcounts */
- GstBuffer *buffer = gst_buffer_copy (buf);
-
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buffer);
- gst_value_array_append_value (array, &value);
- g_value_unset (&value);
-
-}
-
-typedef enum
-{
- PAGE_HEADER, /* Header page */
- PAGE_DATA, /* Data page */
- PAGE_PENDING, /* We don't know yet, we'll have to see some future pages */
-} page_type;
-
-static page_type
-gst_ogg_parse_is_header (GstOggParse * ogg, GstOggStream * stream,
- ogg_page * page)
-{
- ogg_int64_t gpos = ogg_page_granulepos (page);
-
- if (gpos < 0)
- return PAGE_PENDING;
-
- /* This is good enough for now, but technically requires codec-specific
- * behaviour to be perfect. This is where we need the mooted library for
- * this stuff, which nobody has written.
- */
- if (gpos > 0)
- return PAGE_DATA;
- else
- return PAGE_HEADER;
-}
-
-static GstBuffer *
-gst_ogg_parse_buffer_from_page (ogg_page * page,
- guint64 offset, gboolean delta, GstClockTime timestamp)
-{
- int size = page->header_len + page->body_len;
- GstBuffer *buf = gst_buffer_new_and_alloc (size);
-
- memcpy (GST_BUFFER_DATA (buf), page->header, page->header_len);
- memcpy (GST_BUFFER_DATA (buf) + page->header_len, page->body, page->body_len);
-
- GST_BUFFER_TIMESTAMP (buf) = timestamp;
- GST_BUFFER_OFFSET (buf) = offset;
- GST_BUFFER_OFFSET_END (buf) = offset + size;
-
- return buf;
-}
-
-
-/* Reads in buffers, parses them, reframes into one-buffer-per-ogg-page, submits
- * pages to output pad.
- */
-static GstFlowReturn
-gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstOggParse *ogg;
- GstFlowReturn result = GST_FLOW_OK;
- gint ret = -1;
- guint32 serialno;
- GstBuffer *pagebuffer;
- GstClockTime buffertimestamp = GST_BUFFER_TIMESTAMP (buffer);
-
- ogg = GST_OGG_PARSE (GST_OBJECT_PARENT (pad));
-
- GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d",
- GST_BUFFER_SIZE (buffer));
-
- gst_ogg_parse_submit_buffer (ogg, buffer);
-
- while (ret != 0 && result == GST_FLOW_OK) {
- ogg_page page;
-
- /* We use ogg_sync_pageseek() rather than ogg_sync_pageout() so that we can
- * track how many bytes the ogg layer discarded (in the case of sync errors,
- * etc.); this allows us to accurately track the current stream offset
- */
- ret = ogg_sync_pageseek (&ogg->sync, &page);
- if (ret == 0) {
- /* need more data, that's fine... */
- break;
- } else if (ret < 0) {
- /* discontinuity; track how many bytes we skipped (-ret) */
- ogg->offset -= ret;
- } else {
-#ifndef GST_DISABLE_GST_DEBUG
- gint64 granule = ogg_page_granulepos (&page);
- int bos = ogg_page_bos (&page);
-#endif
- guint64 startoffset = ogg->offset;
-
- GST_LOG_OBJECT (ogg, "Timestamping outgoing buffer as %" GST_TIME_FORMAT,
- GST_TIME_ARGS (buffertimestamp));
- /* Turn our page into a GstBuffer TODO: better timestamps? Requires format
- * parsing. */
- pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset, FALSE,
- buffertimestamp);
-
- /* We read out 'ret' bytes, so we set the next offset appropriately */
- ogg->offset += ret;
-
- serialno = ogg_page_serialno (&page);
-
- GST_LOG_OBJECT (ogg,
- "processing ogg page (serial %08x, pageno %ld, "
- "granule pos %" G_GUINT64_FORMAT ", bos %d, offset %"
- G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ")",
- serialno, ogg_page_pageno (&page),
- granule, bos, startoffset, ogg->offset);
-
- if (ogg_page_bos (&page)) {
- /* If we've seen this serialno before, this is technically an error,
- * we log this case but accept it - this one replaces the previous
- * stream with this serialno. We can do this since we're streaming, and
- * not supporting seeking...
- */
- GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);
-
- if (stream != NULL) {
- GST_LOG_OBJECT (ogg, "Incorrect stream; repeats serial number %u "
- "at offset %lld", serialno, ogg->offset);
- }
-
- if (ogg->last_page_not_bos) {
- GST_LOG_OBJECT (ogg, "Deleting all referenced streams, found a new "
- "chain starting with serial %u", serialno);
- gst_ogg_parse_delete_all_streams (ogg);
- }
-
- stream = gst_ogg_parse_new_stream (ogg, serialno);
-
- ogg->last_page_not_bos = FALSE;
-
- gst_buffer_ref (pagebuffer);
- stream->headers = g_slist_append (stream->headers, pagebuffer);
-
- if (!ogg->in_headers) {
- GST_LOG_OBJECT (ogg, "Found start of new chain at offset %llu",
- startoffset);
- ogg->in_headers = 1;
- }
-
- /* For now, we just keep the header buffer in the stream->headers list;
- * it actually gets output once we've collected the entire set
- */
- } else {
- /* Non-BOS page. Either: we're outside headers, and this isn't a
- * header (normal data), outside headers and this is (error!), inside
- * headers, this is (append header), or inside headers and this isn't
- * (we've found the end of headers; flush the lot!)
- *
- * Before that, we flag that the last page seen (this one) was not a
- * BOS page; that way we know that when we next see a BOS page it's a
- * new chain, and we can flush all existing streams.
- */
- page_type type;
- GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno);
-
- if (!stream) {
- GST_LOG_OBJECT (ogg, "Non-BOS page unexpectedly found at %lld",
- ogg->offset);
- goto failure;
- }
-
- ogg->last_page_not_bos = TRUE;
-
- type = gst_ogg_parse_is_header (ogg, stream, &page);
-
- if (type == PAGE_PENDING && ogg->in_headers) {
- gst_buffer_ref (pagebuffer);
-
- stream->unknown_pages = g_slist_append (stream->unknown_pages,
- pagebuffer);
- } else if (type == PAGE_HEADER) {
- if (!ogg->in_headers) {
- GST_LOG_OBJECT (ogg, "Header page unexpectedly found outside "
- "headers at offset %lld", ogg->offset);
- goto failure;
- } else {
- /* Append the header to the buffer list, after any unknown previous
- * pages
- */
- stream->headers = g_slist_concat (stream->headers,
- stream->unknown_pages);
- g_slist_free (stream->unknown_pages);
- gst_buffer_ref (pagebuffer);
- stream->headers = g_slist_append (stream->headers, pagebuffer);
- }
- } else { /* PAGE_DATA, or PAGE_PENDING but outside headers */
- if (ogg->in_headers) {
- /* First non-header page... set caps, flush headers.
- *
- * First up, we build a single GValue list of all the pagebuffers
- * we're using for the headers, in order.
- * Then we set this on the caps structure. Then we can start pushing
- * buffers for the headers, and finally we send this non-header
- * page.
- */
- GstCaps *caps;
- GstStructure *structure;
- GValue array = { 0 };
- gint count = 0;
- gboolean found_pending_headers = FALSE;
- GSList *l;
-
- g_value_init (&array, GST_TYPE_ARRAY);
-
- for (l = ogg->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
-
- if (g_slist_length (stream->headers) == 0) {
- GST_LOG_OBJECT (ogg, "No primary header found for stream %u",
- stream->serialno);
- goto failure;
- }
-
- gst_ogg_parse_append_header (&array,
- GST_BUFFER (stream->headers->data));
- count++;
- }
-
- for (l = ogg->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
- int j;
-
- for (j = 1; j < g_slist_length (stream->headers); j++) {
- gst_ogg_parse_append_header (&array,
- GST_BUFFER (g_slist_nth_data (stream->headers, j)));
- count++;
- }
- }
-
- caps = gst_pad_get_caps (ogg->srcpad);
- caps = gst_caps_make_writable (caps);
-
- structure = gst_caps_get_structure (caps, 0);
- gst_structure_set_value (structure, "streamheader", &array);
-
- gst_pad_set_caps (ogg->srcpad, caps);
-
- g_value_unset (&array);
-
- if (ogg->caps)
- gst_caps_unref (ogg->caps);
- ogg->caps = caps;
-
- GST_LOG_OBJECT (ogg, "Set \"streamheader\" caps with %d buffers "
- "(one per page)", count);
-
- /* Now, we do the same thing, but push buffers... */
- for (l = ogg->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
- GstBuffer *buf = GST_BUFFER (stream->headers->data);
-
- gst_buffer_set_caps (buf, caps);
-
- result = gst_pad_push (ogg->srcpad, buf);
- if (result != GST_FLOW_OK)
- return result;
- }
- for (l = ogg->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
- int j;
-
- for (j = 1; j < g_slist_length (stream->headers); j++) {
- GstBuffer *buf =
- GST_BUFFER (g_slist_nth_data (stream->headers, j));
- gst_buffer_set_caps (buf, caps);
-
- result = gst_pad_push (ogg->srcpad, buf);
- if (result != GST_FLOW_OK)
- return result;
- }
- }
-
- ogg->in_headers = 0;
-
- /* And finally the pending data pages */
- for (l = ogg->oggstreams; l != NULL; l = l->next) {
- GstOggStream *stream = (GstOggStream *) l->data;
- GSList *k;
-
- if (stream->unknown_pages == NULL)
- continue;
-
- if (found_pending_headers) {
- GST_WARNING_OBJECT (ogg, "Incorrectly muxed headers found at "
- "approximate offset %lld", ogg->offset);
- }
- found_pending_headers = TRUE;
-
- GST_LOG_OBJECT (ogg, "Pushing %d pending pages after headers",
- g_slist_length (stream->unknown_pages) + 1);
-
- for (k = stream->unknown_pages; k != NULL; k = k->next) {
- GstBuffer *buf;
-
- buf = GST_BUFFER (k->data);
- gst_buffer_set_caps (buf, caps);
- result = gst_pad_push (ogg->srcpad, buf);
- if (result != GST_FLOW_OK)
- return result;
- }
- g_slist_foreach (stream->unknown_pages,
- (GFunc) gst_mini_object_unref, NULL);
- g_slist_free (stream->unknown_pages);
- stream->unknown_pages = NULL;
- }
-
- gst_buffer_set_caps (pagebuffer, caps);
-
- result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
- if (result != GST_FLOW_OK)
- return result;
- } else {
- /* Normal data page, submit buffer */
- gst_buffer_set_caps (pagebuffer, ogg->caps);
- result = gst_pad_push (ogg->srcpad, GST_BUFFER (pagebuffer));
- if (result != GST_FLOW_OK)
- return result;
- }
- }
- }
- }
- }
-
- return result;
-
-failure:
- gst_pad_push_event (GST_PAD (ogg->srcpad), gst_event_new_eos ());
- return GST_FLOW_ERROR;
-}
-
-static GstStateChangeReturn
-gst_ogg_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstOggParse *ogg;
- GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
-
- ogg = GST_OGG_PARSE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- ogg_sync_init (&ogg->sync);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- ogg_sync_reset (&ogg->sync);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- result = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- ogg_sync_clear (&ogg->sync);
- break;
- default:
- break;
- }
- return result;
-}
-
-gboolean
-gst_ogg_parse_plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_ogg_parse_debug, "oggparse", 0, "ogg parser");
-
- return gst_element_register (plugin, "oggparse", GST_RANK_NONE,
- GST_TYPE_OGG_PARSE);
-}
--- a/gst_plugins_base/ext/ogg/gstogmparse.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,956 +0,0 @@
-/* GStreamer OGM parsing
- * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
- * Copyright (C) 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include <gst/gst.h>
-#include <gst/tag/tag.h>
-#include <gst/riff/riff-media.h>
-#include <gst/riff/riff-read.h>
-
-GST_DEBUG_CATEGORY_STATIC (gst_ogm_parse_debug);
-#define GST_CAT_DEFAULT gst_ogm_parse_debug
-
-#define GST_TYPE_OGM_VIDEO_PARSE (gst_ogm_video_parse_get_type())
-#define GST_IS_OGM_VIDEO_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_VIDEO_PARSE))
-
-#define GST_TYPE_OGM_AUDIO_PARSE (gst_ogm_audio_parse_get_type())
-#define GST_IS_OGM_AUDIO_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_AUDIO_PARSE))
-
-#define GST_TYPE_OGM_TEXT_PARSE (gst_ogm_text_parse_get_type())
-#define GST_IS_OGM_TEXT_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_TEXT_PARSE))
-
-#define GST_TYPE_OGM_PARSE (gst_ogm_parse_get_type())
-#define GST_OGM_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_OGM_PARSE, GstOgmParse))
-#define GST_OGM_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_OGM_PARSE, GstOgmParse))
-#define GST_IS_OGM_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_PARSE))
-#define GST_IS_OGM_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_OGM_PARSE))
-#define GST_OGM_PARSE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_OGM_PARSE, GstOgmParseClass))
-
-static const GstElementDetails gst_ogm_audio_parse_details =
-GST_ELEMENT_DETAILS ("OGM audio stream parser",
- "Codec/Decoder/Audio",
- "parse an OGM audio header and stream",
- "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-static const GstElementDetails gst_ogm_video_parse_details =
-GST_ELEMENT_DETAILS ("OGM video stream parser",
- "Codec/Decoder/Video",
- "parse an OGM video header and stream",
- "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-static const GstElementDetails gst_ogm_text_parse_details =
-GST_ELEMENT_DETAILS ("OGM text stream parser",
- "Codec/Decoder/Subtitle",
- "parse an OGM text header and stream",
- "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-typedef struct _stream_header_video
-{
- gint32 width;
- gint32 height;
-} stream_header_video;
-
-typedef struct _stream_header_audio
-{
- gint16 channels;
- gint16 blockalign;
- gint32 avgbytespersec;
-} stream_header_audio;
-
-/* sizeof(stream_header) might differ due to structure packing and
- * alignment differences on some architectures, so not using that */
-#define OGM_STREAM_HEADER_SIZE (8+4+4+8+8+4+4+4+8)
-
-typedef struct _stream_header
-{
- gchar streamtype[8];
- gchar subtype[4 + 1];
-
- /* size of the structure */
- gint32 size;
-
- /* in reference time */
- gint64 time_unit;
-
- gint64 samples_per_unit;
-
- /* in media time */
- gint32 default_len;
-
- gint32 buffersize;
- gint32 bits_per_sample;
-
- union
- {
- stream_header_video video;
- stream_header_audio audio;
- /* text has no additional data */
- } s;
-} stream_header;
-
-typedef struct _GstOgmParse
-{
- GstElement element;
-
- /* pads */
- GstPad *srcpad, *sinkpad;
- GstPadTemplate *srcpadtempl;
-
- /* we need to cache events that we receive before creating the source pad */
- GList *cached_events;
-
- /* audio or video */
- stream_header hdr;
-
- /* expected next granulepos (used for timestamp guessing) */
- guint64 next_granulepos;
-} GstOgmParse;
-
-typedef struct _GstOgmParseClass
-{
- GstElementClass parent_class;
-} GstOgmParseClass;
-
-static GstStaticPadTemplate sink_factory_video =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-ogm-video"));
-static GstStaticPadTemplate sink_factory_audio =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-ogm-audio"));
-static GstStaticPadTemplate sink_factory_text =
-GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("application/x-ogm-text"));
-static GstPadTemplate *video_src_templ, *audio_src_templ, *text_src_templ;
-
-static GType gst_ogm_audio_parse_get_type (void);
-static GType gst_ogm_video_parse_get_type (void);
-static GType gst_ogm_text_parse_get_type (void);
-static GType gst_ogm_parse_get_type (void);
-
-static void gst_ogm_audio_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_video_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_text_parse_base_init (GstOgmParseClass * klass);
-static void gst_ogm_parse_class_init (GstOgmParseClass * klass);
-static void gst_ogm_parse_init (GstOgmParse * ogm);
-static void gst_ogm_video_parse_init (GstOgmParse * ogm);
-static void gst_ogm_audio_parse_init (GstOgmParse * ogm);
-static void gst_ogm_text_parse_init (GstOgmParse * ogm);
-
-static const GstQueryType *gst_ogm_parse_get_sink_querytypes (GstPad * pad);
-static gboolean gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query);
-static gboolean gst_ogm_parse_sink_convert (GstPad * pad, GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
-
-static GstFlowReturn gst_ogm_parse_chain (GstPad * pad, GstBuffer * buffer);
-
-static GstStateChangeReturn gst_ogm_parse_change_state (GstElement * element,
- GstStateChange transition);
-
-static GstElementClass *parent_class = NULL;
-
-static GType
-gst_ogm_parse_get_type (void)
-{
- static GType ogm_parse_type = 0;
-
- if (!ogm_parse_type) {
- static const GTypeInfo ogm_parse_info = {
- sizeof (GstOgmParseClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_ogm_parse_class_init,
- NULL,
- NULL,
- sizeof (GstOgmParse),
- 0,
- (GInstanceInitFunc) gst_ogm_parse_init,
- };
-
- ogm_parse_type =
- g_type_register_static (GST_TYPE_ELEMENT,
- "GstOgmParse", &ogm_parse_info, 0);
- }
-
- return ogm_parse_type;
-}
-
-static GType
-gst_ogm_audio_parse_get_type (void)
-{
- static GType ogm_audio_parse_type = 0;
-
- if (!ogm_audio_parse_type) {
- static const GTypeInfo ogm_audio_parse_info = {
- sizeof (GstOgmParseClass),
- (GBaseInitFunc) gst_ogm_audio_parse_base_init,
- NULL,
- NULL,
- NULL,
- NULL,
- sizeof (GstOgmParse),
- 0,
- (GInstanceInitFunc) gst_ogm_audio_parse_init,
- };
-
- ogm_audio_parse_type =
- g_type_register_static (GST_TYPE_OGM_PARSE,
- "GstOgmAudioParse", &ogm_audio_parse_info, 0);
- }
-
- return ogm_audio_parse_type;
-}
-
-static GType
-gst_ogm_video_parse_get_type (void)
-{
- static GType ogm_video_parse_type = 0;
-
- if (!ogm_video_parse_type) {
- static const GTypeInfo ogm_video_parse_info = {
- sizeof (GstOgmParseClass),
- (GBaseInitFunc) gst_ogm_video_parse_base_init,
- NULL,
- NULL,
- NULL,
- NULL,
- sizeof (GstOgmParse),
- 0,
- (GInstanceInitFunc) gst_ogm_video_parse_init,
- };
-
- ogm_video_parse_type =
- g_type_register_static (GST_TYPE_OGM_PARSE,
- "GstOgmVideoParse", &ogm_video_parse_info, 0);
- }
-
- return ogm_video_parse_type;
-}
-
-static GType
-gst_ogm_text_parse_get_type (void)
-{
- static GType ogm_text_parse_type = 0;
-
- if (!ogm_text_parse_type) {
- static const GTypeInfo ogm_text_parse_info = {
- sizeof (GstOgmParseClass),
- (GBaseInitFunc) gst_ogm_text_parse_base_init,
- NULL,
- NULL,
- NULL,
- NULL,
- sizeof (GstOgmParse),
- 0,
- (GInstanceInitFunc) gst_ogm_text_parse_init,
- };
-
- ogm_text_parse_type =
- g_type_register_static (GST_TYPE_OGM_PARSE,
- "GstOgmTextParse", &ogm_text_parse_info, 0);
- }
-
- return ogm_text_parse_type;
-}
-
-static void
-gst_ogm_audio_parse_base_init (GstOgmParseClass * klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstCaps *caps = gst_riff_create_audio_template_caps ();
-
- gst_element_class_set_details (element_class, &gst_ogm_audio_parse_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory_audio));
- audio_src_templ = gst_pad_template_new ("src",
- GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
- gst_element_class_add_pad_template (element_class, audio_src_templ);
-}
-
-static void
-gst_ogm_video_parse_base_init (GstOgmParseClass * klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstCaps *caps = gst_riff_create_video_template_caps ();
-
- gst_element_class_set_details (element_class, &gst_ogm_video_parse_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory_video));
- video_src_templ = gst_pad_template_new ("src",
- GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
- gst_element_class_add_pad_template (element_class, video_src_templ);
-}
-
-static void
-gst_ogm_text_parse_base_init (GstOgmParseClass * klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
- GstCaps *caps = gst_caps_new_simple ("text/plain", NULL, NULL);
-
- gst_element_class_set_details (element_class, &gst_ogm_text_parse_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory_text));
- text_src_templ = gst_pad_template_new ("src",
- GST_PAD_SRC, GST_PAD_SOMETIMES, caps);
- gst_element_class_add_pad_template (element_class, text_src_templ);
-}
-
-static void
-gst_ogm_parse_class_init (GstOgmParseClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_ogm_parse_change_state);
-}
-
-static void
-gst_ogm_parse_init (GstOgmParse * ogm)
-{
- memset (&ogm->hdr, 0, sizeof (ogm->hdr));
- ogm->next_granulepos = 0;
- ogm->srcpad = NULL;
- ogm->cached_events = NULL;
-}
-
-static void
-gst_ogm_audio_parse_init (GstOgmParse * ogm)
-{
- ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_audio, "sink");
- gst_pad_set_query_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
- gst_pad_set_chain_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
- gst_pad_set_event_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
- gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
- ogm->srcpad = NULL;
- ogm->srcpadtempl = audio_src_templ;
-}
-
-static void
-gst_ogm_video_parse_init (GstOgmParse * ogm)
-{
- ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_video, "sink");
- gst_pad_set_query_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
- gst_pad_set_chain_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
- gst_pad_set_event_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
- gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
- ogm->srcpad = NULL;
- ogm->srcpadtempl = video_src_templ;
-}
-
-static void
-gst_ogm_text_parse_init (GstOgmParse * ogm)
-{
- ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_text, "sink");
- gst_pad_set_query_type_function (ogm->sinkpad,
- gst_ogm_parse_get_sink_querytypes);
- gst_pad_set_query_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query));
- gst_pad_set_chain_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_chain));
- gst_pad_set_event_function (ogm->sinkpad,
- GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event));
- gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad);
-
- ogm->srcpad = NULL;
- ogm->srcpadtempl = text_src_templ;
-}
-
-static const GstQueryType *
-gst_ogm_parse_get_sink_querytypes (GstPad * pad)
-{
- static const GstQueryType types[] = {
- GST_QUERY_POSITION,
- 0
- };
-
- return types;
-}
-
-static gboolean
-gst_ogm_parse_sink_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = FALSE;
- GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
-
- switch (src_format) {
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- switch (ogm->hdr.streamtype[0]) {
- case 'a':
- *dest_value = GST_SECOND * src_value / ogm->hdr.samples_per_unit;
- res = TRUE;
- break;
- case 'v':
- case 't':
- *dest_value = (GST_SECOND / 10000000) *
- ogm->hdr.time_unit * src_value;
- res = TRUE;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- switch (ogm->hdr.streamtype[0]) {
- case 'a':
- *dest_value = ogm->hdr.samples_per_unit * src_value / GST_SECOND;
- res = TRUE;
- break;
- case 'v':
- case 't':
- *dest_value = src_value /
- ((GST_SECOND / 10000000) * ogm->hdr.time_unit);
- res = TRUE;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- gst_object_unref (ogm);
- return res;
-}
-
-static gboolean
-gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query)
-{
- GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
- GstFormat format;
- gboolean res = FALSE;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 val;
-
- gst_query_parse_position (query, &format, NULL);
-
- if (format != GST_FORMAT_DEFAULT && format != GST_FORMAT_TIME)
- break;
-
- if ((res = gst_ogm_parse_sink_convert (pad,
- GST_FORMAT_DEFAULT, ogm->next_granulepos, &format, &val))) {
- /* don't know the total length here.. */
- gst_query_set_position (query, format, val);
- }
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- /* peel off input */
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if ((res = gst_ogm_parse_sink_convert (pad, src_fmt, src_val,
- &dest_fmt, &dest_val))) {
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- }
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
- gst_object_unref (ogm);
- return res;
-}
-
-static GstFlowReturn
-gst_ogm_parse_stream_header (GstOgmParse * ogm, const guint8 * data, guint size)
-{
- GstCaps *caps = NULL;
-
- /* stream header */
- if (size < OGM_STREAM_HEADER_SIZE)
- goto buffer_too_small;
-
- if (!memcmp (data, "video\000\000\000", 8)) {
- ogm->hdr.s.video.width = GST_READ_UINT32_LE (&data[44]);
- ogm->hdr.s.video.height = GST_READ_UINT32_LE (&data[48]);
- } else if (!memcmp (data, "audio\000\000\000", 8)) {
- ogm->hdr.s.audio.channels = GST_READ_UINT32_LE (&data[44]);
- ogm->hdr.s.audio.blockalign = GST_READ_UINT32_LE (&data[46]);
- ogm->hdr.s.audio.avgbytespersec = GST_READ_UINT32_LE (&data[48]);
- } else if (!memcmp (data, "text\000\000\000\000", 8)) {
- /* nothing here */
- } else {
- goto cannot_decode;
- }
- memcpy (ogm->hdr.streamtype, &data[0], 8);
- memcpy (ogm->hdr.subtype, &data[8], 4);
- ogm->hdr.subtype[4] = '\0';
- ogm->hdr.size = GST_READ_UINT32_LE (&data[12]);
- ogm->hdr.time_unit = GST_READ_UINT64_LE (&data[16]);
- ogm->hdr.samples_per_unit = GST_READ_UINT64_LE (&data[24]);
- ogm->hdr.default_len = GST_READ_UINT32_LE (&data[32]);
- ogm->hdr.buffersize = GST_READ_UINT32_LE (&data[36]);
- ogm->hdr.bits_per_sample = GST_READ_UINT32_LE (&data[40]);
-
- switch (ogm->hdr.streamtype[0]) {
- case 'a':{
- guint codec_id = 0;
-
- if (sscanf (ogm->hdr.subtype, "%04x", &codec_id) != 1) {
- GST_WARNING_OBJECT (ogm, "cannot parse subtype %s", ogm->hdr.subtype);
- }
-
- caps =
- gst_riff_create_audio_caps (codec_id, NULL, NULL, NULL, NULL, NULL);
-
- if (caps == NULL) {
- GST_WARNING_OBJECT (ogm, "no audio caps for codec %u found", codec_id);
- caps = gst_caps_new_simple ("audio/x-ogm-unknown", "codec_id",
- G_TYPE_INT, (gint) codec_id, NULL);
- }
-
- gst_caps_set_simple (caps,
- "channels", G_TYPE_INT, ogm->hdr.s.audio.channels,
- "rate", G_TYPE_INT, ogm->hdr.samples_per_unit, NULL);
-
- GST_LOG_OBJECT (ogm, "Type: %s, subtype: 0x%04x, channels: %d, "
- "samplerate: %d, blockalign: %d, bps: %d, caps = %" GST_PTR_FORMAT,
- ogm->hdr.streamtype, codec_id, ogm->hdr.s.audio.channels,
- (gint) ogm->hdr.samples_per_unit, ogm->hdr.s.audio.blockalign,
- ogm->hdr.s.audio.avgbytespersec, caps);
- break;
- }
- case 'v':{
- guint32 fourcc;
-
- fourcc = GST_MAKE_FOURCC (ogm->hdr.subtype[0],
- ogm->hdr.subtype[1], ogm->hdr.subtype[2], ogm->hdr.subtype[3]);
-
- caps = gst_riff_create_video_caps (fourcc, NULL, NULL, NULL, NULL, NULL);
-
- if (caps == NULL) {
- GST_WARNING_OBJECT (ogm, "could not find video caps for fourcc %"
- GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
- caps = gst_caps_new_simple ("video/x-ogm-unknown", "fourcc",
- GST_TYPE_FOURCC, fourcc, NULL);
- break;
- }
-
- GST_LOG_OBJECT (ogm, "Type: %s, subtype: %" GST_FOURCC_FORMAT
- ", size: %dx%d, timeunit: %" G_GINT64_FORMAT
- " (fps: %lf), s/u: %" G_GINT64_FORMAT ", "
- "def.len: %d, bufsize: %d, bps: %d, caps = %" GST_PTR_FORMAT,
- ogm->hdr.streamtype, GST_FOURCC_ARGS (fourcc),
- ogm->hdr.s.video.width, ogm->hdr.s.video.height,
- ogm->hdr.time_unit, 10000000. / ogm->hdr.time_unit,
- ogm->hdr.samples_per_unit, ogm->hdr.default_len,
- ogm->hdr.buffersize, ogm->hdr.bits_per_sample, caps);
-
- gst_caps_set_simple (caps,
- "width", G_TYPE_INT, ogm->hdr.s.video.width,
- "height", G_TYPE_INT, ogm->hdr.s.video.height,
- "framerate", GST_TYPE_FRACTION, 10000000, ogm->hdr.time_unit, NULL);
- break;
- }
- case 't':{
- GST_LOG_OBJECT (ogm, "Type: %s, s/u: %" G_GINT64_FORMAT
- ", timeunit=%" G_GINT64_FORMAT,
- ogm->hdr.streamtype, ogm->hdr.samples_per_unit, ogm->hdr.time_unit);
- caps = gst_caps_new_simple ("text/plain", NULL);
- break;
- }
- default:
- g_assert_not_reached ();
- }
-
- if (caps == NULL)
- goto cannot_decode;
-
- if (ogm->srcpad) {
- GstCaps *current_caps = GST_PAD_CAPS (ogm->srcpad);
-
- if (current_caps && caps && !gst_caps_is_equal (current_caps, caps)) {
- GST_WARNING_OBJECT (ogm, "Already an existing pad %s:%s",
- GST_DEBUG_PAD_NAME (ogm->srcpad));
- gst_pad_set_active (ogm->srcpad, FALSE);
- gst_element_remove_pad (GST_ELEMENT (ogm), ogm->srcpad);
- ogm->srcpad = NULL;
- } else {
- GST_DEBUG_OBJECT (ogm, "Existing pad has the same caps, do nothing");
- }
- }
-
- if (ogm->srcpad == NULL) {
- GList *l, *cached_events;
-
- ogm->srcpad = gst_pad_new_from_template (ogm->srcpadtempl, "src");
- gst_pad_use_fixed_caps (ogm->srcpad);
- gst_pad_set_caps (ogm->srcpad, caps);
- gst_pad_set_active (ogm->srcpad, TRUE);
- gst_element_add_pad (GST_ELEMENT (ogm), ogm->srcpad);
- GST_INFO_OBJECT (ogm, "Added pad %s:%s with caps %" GST_PTR_FORMAT,
- GST_DEBUG_PAD_NAME (ogm->srcpad), caps);
-
- GST_OBJECT_LOCK (ogm);
- cached_events = ogm->cached_events;
- ogm->cached_events = NULL;
- GST_OBJECT_UNLOCK (ogm);
-
- for (l = cached_events; l; l = l->next) {
- GstEvent *event = GST_EVENT_CAST (l->data);
-
- GST_DEBUG_OBJECT (ogm, "Pushing cached event %" GST_PTR_FORMAT, event);
- gst_pad_push_event (ogm->srcpad, event);
- }
- g_list_free (cached_events);
- }
-
- gst_caps_unref (caps);
-
- return GST_FLOW_OK;
-
-/* ERRORS */
-buffer_too_small:
- {
- GST_ELEMENT_ERROR (ogm, STREAM, WRONG_TYPE, ("Buffer too small"), (NULL));
- return GST_FLOW_ERROR;
- }
-cannot_decode:
- {
- GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("unknown ogm format"));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_ogm_parse_comment_packet (GstOgmParse * ogm, GstBuffer * buf)
-{
- GstFlowReturn ret;
-
- if (ogm->srcpad == NULL) {
- GST_DEBUG ("no source pad");
- return GST_FLOW_WRONG_STATE;
- }
-
- /* if this is not a subtitle stream, push the vorbiscomment packet
- * on downstream, the respective decoder will handle it; if it is
- * a subtitle stream, we will have to handle the comment ourself */
- if (ogm->hdr.streamtype[0] == 't') {
- GstTagList *tags;
-
- tags = gst_tag_list_from_vorbiscomment_buffer (buf,
- (guint8 *) "\003vorbis", 7, NULL);
-
- if (tags) {
- GST_DEBUG_OBJECT (ogm, "tags = %" GST_PTR_FORMAT, tags);
- gst_element_found_tags_for_pad (GST_ELEMENT (ogm), ogm->srcpad, tags);
- } else {
- GST_DEBUG_OBJECT (ogm, "failed to extract tags from vorbis comment");
- }
- /* do not push packet downstream, just let parent unref it */
- ret = GST_FLOW_OK;
- } else {
- buf = gst_buffer_copy (buf);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (ogm->srcpad));
- ret = gst_pad_push (ogm->srcpad, buf);
- }
-
- return ret;
-}
-
-static void
-gst_ogm_text_parse_strip_trailing_zeroes (GstOgmParse * ogm, GstBuffer * buf)
-{
- const guint8 *data;
- guint size;
-
- g_assert (gst_buffer_is_metadata_writable (buf));
-
- /* zeroes are not valid UTF-8 characters, so strip them from output */
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
- while (size > 0 && data[size - 1] == '\0') {
- --size;
- }
-
- GST_BUFFER_SIZE (buf) = size;
-}
-
-static GstFlowReturn
-gst_ogm_parse_data_packet (GstOgmParse * ogm, GstBuffer * buf)
-{
- GstFlowReturn ret;
- const guint8 *data;
- GstBuffer *sbuf;
- gboolean keyframe;
- guint size, len, n, xsize = 0;
-
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
-
- if ((data[0] & 0x01) != 0)
- goto invalid_startcode;
-
- /* data - push on */
- len = ((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1);
- keyframe = (((data[0] & 0x08) >> 3) != 0);
-
- if ((1 + len) > size)
- goto buffer_too_small;
-
- for (n = len; n > 0; n--) {
- xsize = (xsize << 8) | data[n];
- }
-
- GST_LOG_OBJECT (ogm, "[0x%02x] samples: %d, hdrbytes: %d, datasize: %d",
- data[0], xsize, len, size - len - 1);
-
- sbuf = gst_buffer_create_sub (buf, len + 1, size - len - 1);
-
- if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
- ogm->next_granulepos = GST_BUFFER_OFFSET_END (buf);
-
- switch (ogm->hdr.streamtype[0]) {
- case 't':
- case 'v':{
- GstClockTime ts, next_ts;
- guint samples;
-
- samples = (ogm->hdr.streamtype[0] == 'v') ? 1 : xsize;
-
- if (!keyframe) {
- GST_BUFFER_FLAG_SET (sbuf, GST_BUFFER_FLAG_DELTA_UNIT);
- }
-
- /* shouldn't this be granulepos - samples? (tpm) */
- ts = gst_util_uint64_scale (ogm->next_granulepos,
- ogm->hdr.time_unit * GST_SECOND, 10000000);
- next_ts = gst_util_uint64_scale (ogm->next_granulepos + samples,
- ogm->hdr.time_unit * GST_SECOND, 10000000);
-
- GST_BUFFER_TIMESTAMP (sbuf) = ts;
- GST_BUFFER_DURATION (sbuf) = next_ts - ts;
-
- ogm->next_granulepos += samples;
-
- if (ogm->hdr.streamtype[0] == 't') {
- gst_ogm_text_parse_strip_trailing_zeroes (ogm, sbuf);
- }
- break;
- }
- case 'a':{
- GstClockTime ts, next_ts;
-
- /* shouldn't this be granulepos - samples? (tpm) */
- ts = gst_util_uint64_scale_int (ogm->next_granulepos,
- GST_SECOND, ogm->hdr.samples_per_unit);
- next_ts = gst_util_uint64_scale_int (ogm->next_granulepos + xsize,
- GST_SECOND, ogm->hdr.samples_per_unit);
-
- GST_BUFFER_TIMESTAMP (sbuf) = ts;
- GST_BUFFER_DURATION (sbuf) = next_ts - ts;
-
- ogm->next_granulepos += xsize;
- break;
- }
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (ogm->srcpad) {
- gst_buffer_set_caps (sbuf, GST_PAD_CAPS (ogm->srcpad));
- GST_LOG_OBJECT (ogm, "Pushing buffer with ts=%" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sbuf)));
- ret = gst_pad_push (ogm->srcpad, sbuf);
- if (ret != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (ogm, "Flow on %s:%s = %s",
- GST_DEBUG_PAD_NAME (ogm->srcpad), gst_flow_get_name (ret));
- }
- } else {
- ret = GST_FLOW_WRONG_STATE;
- }
-
- return ret;
-
-/* ERRORS */
-invalid_startcode:
- {
- GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL),
- ("unexpected packet startcode 0x%02x", data[0]));
- return GST_FLOW_ERROR;
- }
-buffer_too_small:
- {
- GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL),
- ("buffer too small, len+1=%u, size=%u", len + 1, size));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_ogm_parse_chain (GstPad * pad, GstBuffer * buf)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstOgmParse *ogm = GST_OGM_PARSE (GST_PAD_PARENT (pad));
- guint8 *data = GST_BUFFER_DATA (buf);
- guint size = GST_BUFFER_SIZE (buf);
-
- if (size < 1)
- goto buffer_too_small;
-
- GST_LOG_OBJECT (ogm, "Packet with start code 0x%02x", data[0]);
-
- switch (data[0]) {
- case 0x01:{
- ret = gst_ogm_parse_stream_header (ogm, data + 1, size - 1);
- break;
- }
- case 0x03:{
- ret = gst_ogm_parse_comment_packet (ogm, buf);
- break;
- }
- default:{
- ret = gst_ogm_parse_data_packet (ogm, buf);
- break;
- }
- }
-
- gst_buffer_unref (buf);
-
- if (ret != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (ogm, "Flow: %s", gst_flow_get_name (ret));
- }
-
- return ret;
-
-/* ERRORS */
-buffer_too_small:
- {
- GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("buffer too small"));
- gst_buffer_unref (buf);
- return GST_FLOW_ERROR;
- }
-}
-
-static gboolean
-gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event)
-{
- GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad));
- gboolean res;
-
- GST_LOG_OBJECT (ogm, "processing %s event", GST_EVENT_TYPE_NAME (event));
-
- GST_OBJECT_LOCK (ogm);
- if (ogm->srcpad == NULL) {
- ogm->cached_events = g_list_append (ogm->cached_events, event);
- GST_OBJECT_UNLOCK (ogm);
- res = TRUE;
- } else {
- GST_OBJECT_UNLOCK (ogm);
- res = gst_pad_event_default (pad, event);
- }
-
- gst_object_unref (ogm);
- return res;
-}
-
-static GstStateChangeReturn
-gst_ogm_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- GstOgmParse *ogm = GST_OGM_PARSE (element);
-
- ret = parent_class->change_state (element, transition);
- if (ret != GST_STATE_CHANGE_SUCCESS)
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- if (ogm->srcpad) {
- gst_pad_set_active (ogm->srcpad, FALSE);
- gst_element_remove_pad (element, ogm->srcpad);
- ogm->srcpad = NULL;
- }
- memset (&ogm->hdr, 0, sizeof (ogm->hdr));
- ogm->next_granulepos = 0;
- g_list_foreach (ogm->cached_events, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (ogm->cached_events);
- ogm->cached_events = NULL;
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-gboolean
-gst_ogm_parse_plugin_init (GstPlugin * plugin)
-{
- gst_riff_init ();
-
- GST_DEBUG_CATEGORY_INIT (gst_ogm_parse_debug, "ogmparse", 0, "ogm parser");
-
- return gst_element_register (plugin, "ogmaudioparse", GST_RANK_PRIMARY,
- GST_TYPE_OGM_AUDIO_PARSE) &&
- gst_element_register (plugin, "ogmvideoparse", GST_RANK_PRIMARY,
- GST_TYPE_OGM_VIDEO_PARSE) &&
- gst_element_register (plugin, "ogmtextparse", GST_RANK_PRIMARY,
- GST_TYPE_OGM_TEXT_PARSE);
-}
--- a/gst_plugins_base/ext/pango/gstclockoverlay.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-clockoverlay
- * @see_also: #GstTextOverlay, #GstTimeOverlay
- *
- * <refsect2>
- * <para>
- * This element overlays the current clock time on top of a video
- * stream. You can position the text and configure the font details
- * using the properties of the #GstTextOverlay class. By default, the
- * time is displayed in the top left corner of the picture, with some
- * padding to the left and to the top.
- * </para>
- * <para>
- * Here is a simple pipeline that displays the current time in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! clockoverlay ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays the current time with some leading
- * text in the bottom right corner of the video picture, with the background
- * of the text being shaded in order to make it more legible on top of a
- * bright video background:
- * <programlisting>
- * gst-launch -v videotestsrc ! clockoverlay halign=right valign=bottom text="Edge City" shaded-background=true ! ffmpegcolorspace ! ximagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gstclockoverlay.h>
-#include <gst/video/video.h>
-#include <time.h>
-
-static const GstElementDetails clock_overlay_details =
-GST_ELEMENT_DETAILS ("Clock overlay",
- "Filter/Editor/Video",
- "Overlays the current clock time on a video stream",
- "Tim-Philipp Müller <tim@centricular.net>");
-
-GST_BOILERPLATE (GstClockOverlay, gst_clock_overlay, GstTextOverlay,
- GST_TYPE_TEXT_OVERLAY)
-
- static void gst_clock_overlay_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &clock_overlay_details);
-}
-
-static gchar *
-gst_clock_overlay_render_time (GstClockOverlay * overlay)
-{
- struct tm *t;
- time_t now;
-
-#ifdef HAVE_LOCALTIME_R
- struct tm dummy;
-#endif
-
- now = time (NULL);
-
-#ifdef HAVE_LOCALTIME_R
- t = localtime_r (&now, &dummy);
-#else
- /* on win32 this apparently returns a per-thread struct which would be fine */
- t = localtime (&now);
-#endif
-
- if (t == NULL)
- return g_strdup ("--:--:--");
-
- return g_strdup_printf ("%02u:%02u:%02u", t->tm_hour, t->tm_min, t->tm_sec);
-}
-
-/* Called with lock held */
-static gchar *
-gst_clock_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
- gchar *time_str, *txt, *ret;
-
- overlay->need_render = TRUE;
-
- txt = g_strdup (overlay->default_text);
-
- time_str = gst_clock_overlay_render_time (GST_CLOCK_OVERLAY (overlay));
- if (txt != NULL && *txt != '\0') {
- ret = g_strdup_printf ("%s %s", txt, time_str);
- } else {
- ret = time_str;
- time_str = NULL;
- }
-
- g_free (txt);
- g_free (time_str);
-
- return ret;
-}
-
-static void
-gst_clock_overlay_class_init (GstClockOverlayClass * klass)
-{
- GstTextOverlayClass *gsttextoverlay_class;
-
- gsttextoverlay_class = (GstTextOverlayClass *) klass;
-
- gsttextoverlay_class->get_text = gst_clock_overlay_get_text;
-}
-
-static void
-gst_clock_overlay_init (GstClockOverlay * overlay, GstClockOverlayClass * klass)
-{
- PangoFontDescription *font_description;
- GstTextOverlay *textoverlay;
- PangoContext *context;
-
- textoverlay = GST_TEXT_OVERLAY (overlay);
-
- context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context;
-
- pango_context_set_language (context, pango_language_from_string ("en_US"));
- pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
-
- font_description = pango_font_description_new ();
- pango_font_description_set_family_static (font_description, "Monospace");
- pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
- pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
- pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
- pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
- pango_font_description_set_size (font_description, 18 * PANGO_SCALE);
- pango_context_set_font_description (context, font_description);
- pango_font_description_free (font_description);
-
- textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
- textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
-}
--- a/gst_plugins_base/ext/pango/gstclockoverlay.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __GST_CLOCK_OVERLAY_H__
-#define __GST_CLOCK_OVERLAY_H__
-
-#include "gsttextoverlay.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_CLOCK_OVERLAY \
- (gst_clock_overlay_get_type())
-#define GST_CLOCK_OVERLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CLOCK_OVERLAY,GstClockOverlay))
-#define GST_CLOCK_OVERLAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CLOCK_OVERLAY,GstClockOverlayClass))
-#define GST_IS_CLOCK_OVERLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CLOCK_OVERLAY))
-#define GST_IS_CLOCK_OVERLAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLOCK_OVERLAY))
-
-typedef struct _GstClockOverlay GstClockOverlay;
-typedef struct _GstClockOverlayClass GstClockOverlayClass;
-
-/**
- * GstClockOverlay:
- *
- * Opaque clockoverlay data structure.
- */
-struct _GstClockOverlay {
- GstTextOverlay textoverlay;
-};
-
-struct _GstClockOverlayClass {
- GstTextOverlayClass parent_class;
-};
-
-GType gst_clock_overlay_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_CLOCK_OVERLAY_H__ */
-
--- a/gst_plugins_base/ext/pango/gsttextoverlay.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1698 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- * Copyright (C) <2006> Julien Moutte <julien@moutte.net>
- * Copyright (C) <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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-textoverlay
- * @see_also: #GstTextRender, #GstClockOverlay, #GstTimeOverlay, #GstSubParse
- *
- * <refsect2>
- * <para>
- * This plugin renders text on top of a video stream. This can be either
- * static text or text from buffers received on the text sink pad, e.g.
- * as produced by the subparse element. If the text sink pad is not linked,
- * the text set via the "text" property will be rendered. If the text sink
- * pad is linked, text will be rendered as it is received on that pad,
- * honouring and matching the buffer timestamps of both input streams.
- * </para>
- * <para>
- * The text can contain newline characters and text wrapping is enabled by
- * default.
- * </para>
- * <para>
- * Here is a simple pipeline that displays a static text in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! textoverlay text="Room A" valign=top halign=left ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays subtitles from an .srt subtitle
- * file, centered at the bottom of the picture and with a rectangular shading
- * around the text in the background:
- * <programlisting>
- * gst-launch -v filesrc location=subtitles.srt ! subparse ! txt. videotestsrc ! timeoverlay ! textoverlay name=txt shaded-background=yes ! xvimagesink
- * </programlisting>
- * If you do not have such a subtitle file, create one looking like this
- * in a text editor:
- * <programlisting>
- * 1
- * 00:00:03,000 --> 00:00:05,000
- * Hello? (3-5s)
- *
- * 2
- * 00:00:08,000 --> 00:00:13,000
- * Yes, this is a subtitle. Don't
- * you like it? (8-13s)
- *
- * 3
- * 00:00:18,826 --> 00:01:02,886
- * Uh? What are you talking about?
- * I don't understand (18-62s)
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-/* FIXME: alloc segment as part of instance struct */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gst/video/video.h>
-
-#include "gsttextoverlay.h"
-#include "gsttimeoverlay.h"
-#include "gstclockoverlay.h"
-#include "gsttextrender.h"
-
-/* FIXME:
- * - use proper strides and offset for I420
- * - if text is wider than the video picture, it does not get
- * clipped properly during blitting (if wrapping is disabled)
- * - make 'shading_value' a property (or enum: light/normal/dark/verydark)?
- */
-
-GST_DEBUG_CATEGORY (pango_debug);
-#define GST_CAT_DEFAULT pango_debug
-
-static const GstElementDetails text_overlay_details =
-GST_ELEMENT_DETAILS ("Text overlay",
- "Filter/Editor/Video",
- "Adds text strings on top of a video buffer",
- "David Schleef <ds@schleef.org>");
-
-
-#define DEFAULT_PROP_TEXT ""
-#define DEFAULT_PROP_SHADING FALSE
-#define DEFAULT_PROP_VALIGNMENT GST_TEXT_OVERLAY_VALIGN_BASELINE
-#define DEFAULT_PROP_HALIGNMENT GST_TEXT_OVERLAY_HALIGN_CENTER
-#define DEFAULT_PROP_VALIGN "baseline"
-#define DEFAULT_PROP_HALIGN "center"
-#define DEFAULT_PROP_XPAD 25
-#define DEFAULT_PROP_YPAD 25
-#define DEFAULT_PROP_DELTAX 0
-#define DEFAULT_PROP_DELTAY 0
-#define DEFAULT_PROP_WRAP_MODE GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR
-#define DEFAULT_PROP_FONT_DESC ""
-#define DEFAULT_PROP_SILENT FALSE
-#define DEFAULT_PROP_LINE_ALIGNMENT GST_TEXT_OVERLAY_LINE_ALIGN_CENTER
-
-/* make a property of me */
-#define DEFAULT_SHADING_VALUE -80
-
-enum
-{
- PROP_0,
- PROP_TEXT,
- PROP_SHADING,
- PROP_VALIGN, /* deprecated */
- PROP_HALIGN, /* deprecated */
- PROP_HALIGNMENT,
- PROP_VALIGNMENT,
- PROP_XPAD,
- PROP_YPAD,
- PROP_DELTAX,
- PROP_DELTAY,
- PROP_WRAP_MODE,
- PROP_FONT_DESC,
- PROP_SILENT,
- PROP_LINE_ALIGNMENT
-};
-
-
-static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
- );
-
-static GstStaticPadTemplate video_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("video_sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
- );
-
-static GstStaticPadTemplate text_sink_template_factory =
- GST_STATIC_PAD_TEMPLATE ("text_sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
- );
-
-
-#define GST_TYPE_TEXT_OVERLAY_VALIGN (gst_text_overlay_valign_get_type())
-static GType
-gst_text_overlay_valign_get_type (void)
-{
- static GType text_overlay_valign_type = 0;
- static const GEnumValue text_overlay_valign[] = {
- {GST_TEXT_OVERLAY_VALIGN_BASELINE, "baseline", "baseline"},
- {GST_TEXT_OVERLAY_VALIGN_BOTTOM, "bottom", "bottom"},
- {GST_TEXT_OVERLAY_VALIGN_TOP, "top", "top"},
- {0, NULL, NULL},
- };
-
- if (!text_overlay_valign_type) {
- text_overlay_valign_type =
- g_enum_register_static ("GstTextOverlayVAlign", text_overlay_valign);
- }
- return text_overlay_valign_type;
-}
-
-#define GST_TYPE_TEXT_OVERLAY_HALIGN (gst_text_overlay_halign_get_type())
-static GType
-gst_text_overlay_halign_get_type (void)
-{
- static GType text_overlay_halign_type = 0;
- static const GEnumValue text_overlay_halign[] = {
- {GST_TEXT_OVERLAY_HALIGN_LEFT, "left", "left"},
- {GST_TEXT_OVERLAY_HALIGN_CENTER, "center", "center"},
- {GST_TEXT_OVERLAY_HALIGN_RIGHT, "right", "right"},
- {0, NULL, NULL},
- };
-
- if (!text_overlay_halign_type) {
- text_overlay_halign_type =
- g_enum_register_static ("GstTextOverlayHAlign", text_overlay_halign);
- }
- return text_overlay_halign_type;
-}
-
-
-#define GST_TYPE_TEXT_OVERLAY_WRAP_MODE (gst_text_overlay_wrap_mode_get_type())
-static GType
-gst_text_overlay_wrap_mode_get_type (void)
-{
- static GType text_overlay_wrap_mode_type = 0;
- static const GEnumValue text_overlay_wrap_mode[] = {
- {GST_TEXT_OVERLAY_WRAP_MODE_NONE, "none", "none"},
- {GST_TEXT_OVERLAY_WRAP_MODE_WORD, "word", "word"},
- {GST_TEXT_OVERLAY_WRAP_MODE_CHAR, "char", "char"},
- {GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR, "wordchar", "wordchar"},
- {0, NULL, NULL},
- };
-
- if (!text_overlay_wrap_mode_type) {
- text_overlay_wrap_mode_type =
- g_enum_register_static ("GstTextOverlayWrapMode",
- text_overlay_wrap_mode);
- }
- return text_overlay_wrap_mode_type;
-}
-
-#define GST_TYPE_TEXT_OVERLAY_LINE_ALIGN (gst_text_overlay_line_align_get_type())
-static GType
-gst_text_overlay_line_align_get_type (void)
-{
- static GType text_overlay_line_align_type = 0;
- static const GEnumValue text_overlay_line_align[] = {
- {GST_TEXT_OVERLAY_LINE_ALIGN_LEFT, "left", "left"},
- {GST_TEXT_OVERLAY_LINE_ALIGN_CENTER, "center", "center"},
- {GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT, "right", "right"},
- {0, NULL, NULL}
- };
-
- if (!text_overlay_line_align_type) {
- text_overlay_line_align_type =
- g_enum_register_static ("GstTextOverlayLineAlign",
- text_overlay_line_align);
- }
- return text_overlay_line_align_type;
-}
-
-/* These macros are adapted from videotestsrc.c */
-#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
-#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
-#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
-
-#define I420_Y_OFFSET(w,h) (0)
-#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
-#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
-
-#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
-
-#define GST_TEXT_OVERLAY_GET_COND(ov) (((GstTextOverlay *)ov)->cond)
-#define GST_TEXT_OVERLAY_WAIT(ov) (g_cond_wait (GST_TEXT_OVERLAY_GET_COND (ov), GST_OBJECT_GET_LOCK (ov)))
-#define GST_TEXT_OVERLAY_SIGNAL(ov) (g_cond_signal (GST_TEXT_OVERLAY_GET_COND (ov)))
-#define GST_TEXT_OVERLAY_BROADCAST(ov)(g_cond_broadcast (GST_TEXT_OVERLAY_GET_COND (ov)))
-
-static GstStateChangeReturn gst_text_overlay_change_state (GstElement * element,
- GstStateChange transition);
-
-static GstCaps *gst_text_overlay_getcaps (GstPad * pad);
-static gboolean gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps);
-static gboolean gst_text_overlay_src_event (GstPad * pad, GstEvent * event);
-
-static gboolean gst_text_overlay_video_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_text_overlay_video_chain (GstPad * pad,
- GstBuffer * buffer);
-
-static gboolean gst_text_overlay_text_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_text_overlay_text_chain (GstPad * pad,
- GstBuffer * buffer);
-static GstPadLinkReturn gst_text_overlay_text_pad_link (GstPad * pad,
- GstPad * peer);
-static void gst_text_overlay_text_pad_unlink (GstPad * pad);
-static void gst_text_overlay_pop_text (GstTextOverlay * overlay);
-
-static void gst_text_overlay_finalize (GObject * object);
-static void gst_text_overlay_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_text_overlay_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-GST_BOILERPLATE (GstTextOverlay, gst_text_overlay, GstElement, GST_TYPE_ELEMENT)
-
- static void gst_text_overlay_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&video_sink_template_factory));
-
- /* ugh */
- if (!GST_IS_TIME_OVERLAY_CLASS (g_class) &&
- !GST_IS_CLOCK_OVERLAY_CLASS (g_class)) {
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&text_sink_template_factory));
- }
-
- gst_element_class_set_details (element_class, &text_overlay_details);
-}
-
-static gchar *
-gst_text_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
- return g_strdup (overlay->default_text);
-}
-
-static void
-gst_text_overlay_class_init (GstTextOverlayClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- gobject_class->finalize = gst_text_overlay_finalize;
- gobject_class->set_property = gst_text_overlay_set_property;
- gobject_class->get_property = gst_text_overlay_get_property;
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_text_overlay_change_state);
-
- klass->get_text = gst_text_overlay_get_text;
- klass->pango_context = pango_ft2_get_context (72, 72);
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT,
- g_param_spec_string ("text", "text",
- "Text to be display.", DEFAULT_PROP_TEXT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHADING,
- g_param_spec_boolean ("shaded-background", "shaded background",
- "Whether to shade the background under the text area",
- DEFAULT_PROP_SHADING, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGNMENT,
- g_param_spec_enum ("valignment", "vertical alignment",
- "Vertical alignment of the text",
- GST_TYPE_TEXT_OVERLAY_VALIGN, DEFAULT_PROP_VALIGNMENT,
- G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGNMENT,
- g_param_spec_enum ("halignment", "horizontal alignment",
- "Horizontal alignment of the text", GST_TYPE_TEXT_OVERLAY_HALIGN,
- DEFAULT_PROP_HALIGNMENT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGN,
- g_param_spec_string ("valign", "vertical alignment",
- "Vertical alignment of the text (deprecated; use valignment)",
- DEFAULT_PROP_VALIGN, G_PARAM_WRITABLE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGN,
- g_param_spec_string ("halign", "horizontal alignment",
- "Horizontal alignment of the text (deprecated; use halignment)",
- DEFAULT_PROP_HALIGN, G_PARAM_WRITABLE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPAD,
- g_param_spec_int ("xpad", "horizontal paddding",
- "Horizontal paddding when using left/right alignment", 0, G_MAXINT,
- DEFAULT_PROP_XPAD, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPAD,
- g_param_spec_int ("ypad", "vertical padding",
- "Vertical padding when using top/bottom alignment", 0, G_MAXINT,
- DEFAULT_PROP_YPAD, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAX,
- g_param_spec_int ("deltax", "X position modifier",
- "Shift X position to the left or to the right. Unit is pixels.",
- G_MININT, G_MAXINT, DEFAULT_PROP_DELTAX, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAY,
- g_param_spec_int ("deltay", "Y position modifier",
- "Shift Y position up or down. Unit is pixels.", G_MININT, G_MAXINT,
- DEFAULT_PROP_DELTAY, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WRAP_MODE,
- g_param_spec_enum ("wrap-mode", "wrap mode",
- "Whether to wrap the text and if so how.",
- GST_TYPE_TEXT_OVERLAY_WRAP_MODE, DEFAULT_PROP_WRAP_MODE,
- G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC,
- g_param_spec_string ("font-desc", "font description",
- "Pango font description of font to be used for rendering. "
- "See documentation of pango_font_description_from_string "
- "for syntax.", DEFAULT_PROP_FONT_DESC, G_PARAM_WRITABLE));
- /**
- * GstTextOverlay:line-alignment
- *
- * Alignment of text lines relative to each other (for multi-line text)
- *
- * Since: 0.10.15
- **/
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LINE_ALIGNMENT,
- g_param_spec_enum ("line-alignment", "line alignment",
- "Alignment of text lines relative to each other.",
- GST_TYPE_TEXT_OVERLAY_LINE_ALIGN, DEFAULT_PROP_LINE_ALIGNMENT,
- G_PARAM_READWRITE));
- /**
- * GstTextOverlay:silent
- *
- * If set, no text is rendered. Useful to switch off text rendering
- * temporarily without removing the textoverlay element from the pipeline.
- *
- * Since: 0.10.15
- **/
- /* FIXME 0.11: rename to "visible" or "text-visible" or "render-text" */
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT,
- g_param_spec_boolean ("silent", "silent",
- "Whether to render the text string",
- DEFAULT_PROP_SILENT, G_PARAM_READWRITE));
-}
-
-static void
-gst_text_overlay_finalize (GObject * object)
-{
- GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
- g_free (overlay->default_text);
- g_free (overlay->bitmap.buffer);
-
- if (overlay->layout) {
- g_object_unref (overlay->layout);
- overlay->layout = NULL;
- }
-
- if (overlay->segment) {
- gst_segment_free (overlay->segment);
- overlay->segment = NULL;
- }
-
- if (overlay->text_buffer) {
- gst_buffer_unref (overlay->text_buffer);
- overlay->text_buffer = NULL;
- }
-
- if (overlay->cond) {
- g_cond_free (overlay->cond);
- overlay->cond = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_text_overlay_init (GstTextOverlay * overlay, GstTextOverlayClass * klass)
-{
- GstPadTemplate *template;
-
- /* video sink */
- template = gst_static_pad_template_get (&video_sink_template_factory);
- overlay->video_sinkpad = gst_pad_new_from_template (template, "video_sink");
- gst_object_unref (template);
- gst_pad_set_getcaps_function (overlay->video_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps));
- gst_pad_set_setcaps_function (overlay->video_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps));
- gst_pad_set_event_function (overlay->video_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_video_event));
- gst_pad_set_chain_function (overlay->video_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_video_chain));
- gst_element_add_pad (GST_ELEMENT (overlay), overlay->video_sinkpad);
-
- if (!GST_IS_TIME_OVERLAY_CLASS (klass) && !GST_IS_CLOCK_OVERLAY_CLASS (klass)) {
- /* text sink */
- template = gst_static_pad_template_get (&text_sink_template_factory);
- overlay->text_sinkpad = gst_pad_new_from_template (template, "text_sink");
- gst_object_unref (template);
- gst_pad_set_setcaps_function (overlay->text_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps_txt));
- gst_pad_set_event_function (overlay->text_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_text_event));
- gst_pad_set_chain_function (overlay->text_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_text_chain));
- gst_pad_set_link_function (overlay->text_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_link));
- gst_pad_set_unlink_function (overlay->text_sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_unlink));
- gst_element_add_pad (GST_ELEMENT (overlay), overlay->text_sinkpad);
- }
-
- /* (video) source */
- template = gst_static_pad_template_get (&src_template_factory);
- overlay->srcpad = gst_pad_new_from_template (template, "src");
- gst_object_unref (template);
- gst_pad_set_getcaps_function (overlay->srcpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps));
- gst_pad_set_event_function (overlay->srcpad,
- GST_DEBUG_FUNCPTR (gst_text_overlay_src_event));
- gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad);
-
- overlay->line_align = DEFAULT_PROP_LINE_ALIGNMENT;
- overlay->layout =
- pango_layout_new (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_context);
- pango_layout_set_alignment (overlay->layout,
- (PangoAlignment) overlay->line_align);
- memset (&overlay->bitmap, 0, sizeof (overlay->bitmap));
-
- overlay->halign = DEFAULT_PROP_HALIGNMENT;
- overlay->valign = DEFAULT_PROP_VALIGNMENT;
- overlay->xpad = DEFAULT_PROP_XPAD;
- overlay->ypad = DEFAULT_PROP_YPAD;
- overlay->deltax = DEFAULT_PROP_DELTAX;
- overlay->deltay = DEFAULT_PROP_DELTAY;
-
- overlay->wrap_mode = DEFAULT_PROP_WRAP_MODE;
-
- overlay->want_shading = DEFAULT_PROP_SHADING;
- overlay->shading_value = DEFAULT_SHADING_VALUE;
- overlay->silent = DEFAULT_PROP_SILENT;
-
- overlay->default_text = g_strdup (DEFAULT_PROP_TEXT);
- overlay->need_render = TRUE;
-
- overlay->fps_n = 0;
- overlay->fps_d = 1;
-
- overlay->text_buffer = NULL;
- overlay->text_linked = FALSE;
- overlay->video_flushing = FALSE;
- overlay->text_flushing = FALSE;
- overlay->text_eos = FALSE;
- overlay->cond = g_cond_new ();
- overlay->segment = gst_segment_new ();
- if (overlay->segment) {
- gst_segment_init (overlay->segment, GST_FORMAT_TIME);
- } else {
- GST_WARNING_OBJECT (overlay, "segment creation failed");
- g_assert_not_reached ();
- }
-}
-
-static void
-gst_text_overlay_update_wrap_mode (GstTextOverlay * overlay)
-{
- if (overlay->wrap_mode == GST_TEXT_OVERLAY_WRAP_MODE_NONE) {
- GST_DEBUG_OBJECT (overlay, "Set wrap mode NONE");
- pango_layout_set_width (overlay->layout, -1);
- } else {
- GST_DEBUG_OBJECT (overlay, "Set layout width %d", overlay->width);
- GST_DEBUG_OBJECT (overlay, "Set wrap mode %d", overlay->wrap_mode);
- pango_layout_set_width (overlay->layout, overlay->width * PANGO_SCALE);
- pango_layout_set_wrap (overlay->layout, (PangoWrapMode) overlay->wrap_mode);
- }
-}
-
-static gboolean
-gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps)
-{
- GstTextOverlay *overlay;
- GstStructure *structure;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- structure = gst_caps_get_structure (caps, 0);
- overlay->have_pango_markup =
- gst_structure_has_name (structure, "text/x-pango-markup");
-
- gst_object_unref (overlay);
-
- return TRUE;
-}
-
-/* FIXME: upstream nego (e.g. when the video window is resized) */
-
-static gboolean
-gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstTextOverlay *overlay;
- GstStructure *structure;
- gboolean ret = FALSE;
- const GValue *fps;
-
- if (!GST_PAD_IS_SINK (pad))
- return TRUE;
-
- g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- overlay->width = 0;
- overlay->height = 0;
- structure = gst_caps_get_structure (caps, 0);
- fps = gst_structure_get_value (structure, "framerate");
-
- if (gst_structure_get_int (structure, "width", &overlay->width) &&
- gst_structure_get_int (structure, "height", &overlay->height) &&
- fps != NULL) {
- ret = gst_pad_set_caps (overlay->srcpad, caps);
- }
-
- overlay->fps_n = gst_value_get_fraction_numerator (fps);
- overlay->fps_d = gst_value_get_fraction_denominator (fps);
-
- if (ret) {
- GST_OBJECT_LOCK (overlay);
- gst_text_overlay_update_wrap_mode (overlay);
- GST_OBJECT_UNLOCK (overlay);
- }
-
- gst_object_unref (overlay);
-
- return ret;
-}
-
-static void
-gst_text_overlay_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
- GST_OBJECT_LOCK (overlay);
- switch (prop_id) {
- case PROP_TEXT:
- g_free (overlay->default_text);
- overlay->default_text = g_value_dup_string (value);
- overlay->need_render = TRUE;
- break;
- case PROP_SHADING:
- overlay->want_shading = g_value_get_boolean (value);
- break;
- case PROP_XPAD:
- overlay->xpad = g_value_get_int (value);
- break;
- case PROP_YPAD:
- overlay->ypad = g_value_get_int (value);
- break;
- case PROP_DELTAX:
- overlay->deltax = g_value_get_int (value);
- break;
- case PROP_DELTAY:
- overlay->deltay = g_value_get_int (value);
- break;
- case PROP_HALIGN:{
- const gchar *s = g_value_get_string (value);
-
- if (s && g_ascii_strcasecmp (s, "left") == 0)
- overlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
- else if (s && g_ascii_strcasecmp (s, "center") == 0)
- overlay->halign = GST_TEXT_OVERLAY_HALIGN_CENTER;
- else if (s && g_ascii_strcasecmp (s, "right") == 0)
- overlay->halign = GST_TEXT_OVERLAY_HALIGN_RIGHT;
- else
- g_warning ("Invalid value '%s' for textoverlay property 'halign'",
- GST_STR_NULL (s));
- break;
- }
- case PROP_VALIGN:{
- const gchar *s = g_value_get_string (value);
-
- if (s && g_ascii_strcasecmp (s, "baseline") == 0)
- overlay->valign = GST_TEXT_OVERLAY_VALIGN_BASELINE;
- else if (s && g_ascii_strcasecmp (s, "bottom") == 0)
- overlay->valign = GST_TEXT_OVERLAY_VALIGN_BOTTOM;
- else if (s && g_ascii_strcasecmp (s, "top") == 0)
- overlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
- else
- g_warning ("Invalid value '%s' for textoverlay property 'valign'",
- GST_STR_NULL (s));
- break;
- }
- case PROP_VALIGNMENT:
- overlay->valign = g_value_get_enum (value);
- break;
- case PROP_HALIGNMENT:
- overlay->halign = g_value_get_enum (value);
- break;
- case PROP_WRAP_MODE:
- overlay->wrap_mode = g_value_get_enum (value);
- gst_text_overlay_update_wrap_mode (overlay);
- break;
- case PROP_FONT_DESC:
- {
- PangoFontDescription *desc;
- const gchar *fontdesc_str;
-
- fontdesc_str = g_value_get_string (value);
- desc = pango_font_description_from_string (fontdesc_str);
- if (desc) {
- GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str);
- pango_layout_set_font_description (overlay->layout, desc);
- pango_font_description_free (desc);
- } else {
- GST_WARNING_OBJECT (overlay, "font description parse failed: %s",
- fontdesc_str);
- }
- break;
- }
- case PROP_SILENT:
- overlay->silent = g_value_get_boolean (value);
- break;
- case PROP_LINE_ALIGNMENT:
- overlay->line_align = g_value_get_enum (value);
- pango_layout_set_alignment (overlay->layout,
- (PangoAlignment) overlay->line_align);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- overlay->need_render = TRUE;
- GST_OBJECT_UNLOCK (overlay);
-}
-
-static void
-gst_text_overlay_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTextOverlay *overlay = GST_TEXT_OVERLAY (object);
-
- GST_OBJECT_LOCK (overlay);
- switch (prop_id) {
- case PROP_TEXT:
- g_value_set_string (value, overlay->default_text);
- break;
- case PROP_SHADING:
- g_value_set_boolean (value, overlay->want_shading);
- break;
- case PROP_XPAD:
- g_value_set_int (value, overlay->xpad);
- break;
- case PROP_YPAD:
- g_value_set_int (value, overlay->ypad);
- break;
- case PROP_DELTAX:
- g_value_set_int (value, overlay->deltax);
- break;
- case PROP_DELTAY:
- g_value_set_int (value, overlay->deltay);
- break;
- case PROP_VALIGNMENT:
- g_value_set_enum (value, overlay->valign);
- break;
- case PROP_HALIGNMENT:
- g_value_set_enum (value, overlay->halign);
- break;
- case PROP_WRAP_MODE:
- g_value_set_enum (value, overlay->wrap_mode);
- break;
- case PROP_SILENT:
- g_value_set_boolean (value, overlay->silent);
- break;
- case PROP_LINE_ALIGNMENT:
- g_value_set_enum (value, overlay->line_align);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- overlay->need_render = TRUE;
- GST_OBJECT_UNLOCK (overlay);
-}
-
-static gboolean
-gst_text_overlay_src_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = FALSE;
- GstTextOverlay *overlay = NULL;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- /* We don't handle seek if we have not text pad */
- if (!overlay->text_linked) {
- ret = gst_pad_push_event (overlay->video_sinkpad, event);
- goto beach;
- }
-
- GST_DEBUG_OBJECT (overlay, "seek received, driving from here");
-
- /* Flush downstream, FIXME, only for flushing seek */
- gst_pad_push_event (overlay->srcpad, gst_event_new_flush_start ());
-
- /* Mark ourself as flushing, unblock chains */
- GST_OBJECT_LOCK (overlay);
- overlay->video_flushing = TRUE;
- overlay->text_flushing = TRUE;
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
-
- /* Seek on each sink pad */
- gst_event_ref (event);
- ret = gst_pad_push_event (overlay->video_sinkpad, event);
- if (ret) {
- ret = gst_pad_push_event (overlay->text_sinkpad, event);
- } else {
- gst_event_unref (event);
- }
- break;
- default:
- if (overlay->text_linked) {
- gst_event_ref (event);
- ret = gst_pad_push_event (overlay->video_sinkpad, event);
- gst_pad_push_event (overlay->text_sinkpad, event);
- } else {
- ret = gst_pad_push_event (overlay->video_sinkpad, event);
- }
- break;
- }
-
-beach:
- gst_object_unref (overlay);
-
- return ret;
-}
-
-static GstCaps *
-gst_text_overlay_getcaps (GstPad * pad)
-{
- GstTextOverlay *overlay;
- GstPad *otherpad;
- GstCaps *caps;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- if (pad == overlay->srcpad)
- otherpad = overlay->video_sinkpad;
- else
- otherpad = overlay->srcpad;
-
- /* we can do what the peer can */
- caps = gst_pad_peer_get_caps (otherpad);
- if (caps) {
- GstCaps *temp;
- const GstCaps *templ;
-
- GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps);
-
- /* filtered against our padtemplate */
- templ = gst_pad_get_pad_template_caps (otherpad);
- GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
- temp = gst_caps_intersect (caps, templ);
- GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
- gst_caps_unref (caps);
- /* this is what we can do */
- caps = temp;
- } else {
- /* no peer, our padtemplate is enough then */
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
- }
-
- GST_DEBUG_OBJECT (overlay, "returning %" GST_PTR_FORMAT, caps);
-
- gst_object_unref (overlay);
-
- return caps;
-}
-
-#define BOX_XPAD 6
-#define BOX_YPAD 6
-
-static inline void
-gst_text_overlay_shade_y (GstTextOverlay * overlay, guchar * dest,
- guint dest_stride, gint x0, gint x1, gint y0, gint y1)
-{
- gint i, j;
-
- x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width);
- x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width);
-
- y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height);
- y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height);
-
- for (i = y0; i < y1; ++i) {
- for (j = x0; j < x1; ++j) {
- gint y = dest[(i * dest_stride) + j] + overlay->shading_value;
-
- dest[(i * dest_stride) + j] = CLAMP (y, 0, 255);
- }
- }
-}
-
-/* FIXME:
- * - use proper strides and offset for I420
- * - don't draw over the edge of the picture (try a longer
- * text with a huge font size)
- */
-
-static inline void
-gst_text_overlay_blit_yuv420 (GstTextOverlay * overlay, FT_Bitmap * bitmap,
- guint8 * yuv_pixels, gint x0, gint y0)
-{
- int y; /* text bitmap coordinates */
- int x1, y1; /* video buffer coordinates */
- int bit_rowinc, uv_rowinc;
- guint8 *p, *bitp, *u_p;
- int video_width, video_height;
- int bitmap_x0 = 0; //x0 < 1 ? -(x0 - 1) : 1; /* 1 pixel border */
- int bitmap_y0 = y0 < 1 ? -(y0 - 1) : 1; /* 1 pixel border */
- int bitmap_width = bitmap->width - bitmap_x0;
- int bitmap_height = bitmap->rows - bitmap_y0;
- int u_plane_size;
- int skip_y, skip_x;
- guint8 v;
-
- video_width = I420_Y_ROWSTRIDE (overlay->width);
- video_height = overlay->height;
-
-/*
- if (x0 < 0 && abs (x0) < bitmap_width) {
- bitmap_x0 = abs (x0);
- x0 = 0;
- }
-*/
-
- if (x0 + bitmap_x0 + bitmap_width > overlay->width - 1) /* 1 pixel border */
- bitmap_width -= x0 + bitmap_x0 + bitmap_width - overlay->width + 1;
- if (y0 + bitmap_y0 + bitmap_height > video_height - 1) /* 1 pixel border */
- bitmap_height -= y0 + bitmap_y0 + bitmap_height - video_height + 1;
-
- uv_rowinc = video_width / 2 - bitmap_width / 2;
- bit_rowinc = bitmap->pitch - bitmap_width;
- u_plane_size = (video_width / 2) * (video_height / 2);
-
- y1 = y0 + bitmap_y0;
- x1 = x0 + bitmap_x0;
- bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
- for (y = bitmap_y0; y < bitmap_y0 + bitmap_height; y++) {
- int n;
-
- p = yuv_pixels + (y + y0) * I420_Y_ROWSTRIDE (overlay->width) + x1;
- for (n = bitmap_width; n > 0; --n) {
- v = *bitp;
- if (v) {
- p[-1] = CLAMP (p[-1] - v, 0, 255);
- p[1] = CLAMP (p[1] - v, 0, 255);
- p[-video_width] = CLAMP (p[-video_width] - v, 0, 255);
- p[video_width] = CLAMP (p[video_width] - v, 0, 255);
- }
- p++;
- bitp++;
- }
- bitp += bit_rowinc;
- }
-
- y = bitmap_y0;
- y1 = y0 + bitmap_y0;
- x1 = x0 + bitmap_x0;
- bitp = bitmap->buffer + bitmap->pitch * bitmap_y0 + bitmap_x0;
- p = yuv_pixels + video_width * y1 + x1;
- u_p =
- yuv_pixels + video_width * video_height + (video_width >> 1) * (y1 >> 1) +
- (x1 >> 1);
- skip_y = 0;
- skip_x = 0;
-
- for (; y < bitmap_y0 + bitmap_height; y++) {
- int n;
-
- x1 = x0 + bitmap_x0;
- skip_x = 0;
- for (n = bitmap_width; n > 0; --n) {
- v = *bitp;
- if (v) {
- *p = v;
- if (!skip_y) {
- u_p[0] = u_p[u_plane_size] = 0x80;
- }
- }
- if (!skip_y) {
- skip_x = !skip_x;
- if (!skip_x)
- u_p++;
- }
- p++;
- bitp++;
- }
- /*if (!skip_x && !skip_y) u_p--; */
- p += I420_Y_ROWSTRIDE (overlay->width) - bitmap_width;
- bitp += bit_rowinc;
- skip_y = !skip_y;
- u_p += skip_y ? uv_rowinc : 0;
- }
-}
-
-static void
-gst_text_overlay_resize_bitmap (GstTextOverlay * overlay, gint width,
- gint height)
-{
- FT_Bitmap *bitmap = &overlay->bitmap;
- int pitch = (width | 3) + 1;
- int size = pitch * height;
-
- /* no need to keep reallocating; just keep the maximum size so far */
- if (size <= overlay->bitmap_buffer_size) {
- bitmap->rows = height;
- bitmap->width = width;
- bitmap->pitch = pitch;
- memset (bitmap->buffer, 0, overlay->bitmap_buffer_size);
- return;
- }
- if (!bitmap->buffer) {
- /* initialize */
- bitmap->pixel_mode = ft_pixel_mode_grays;
- bitmap->num_grays = 256;
- }
- overlay->bitmap_buffer_size = size;
- bitmap->buffer = g_realloc (bitmap->buffer, size);
- memset (bitmap->buffer, 0, size);
- bitmap->rows = height;
- bitmap->width = width;
- bitmap->pitch = pitch;
-}
-
-static void
-gst_text_overlay_render_text (GstTextOverlay * overlay,
- const gchar * text, gint textlen)
-{
- PangoRectangle ink_rect, logical_rect;
- gchar *string;
-
- if (!overlay->need_render) {
- GST_DEBUG ("Using previously rendered text.");
- return;
- }
-
- /* -1 is the whole string */
- if (text != NULL && textlen < 0) {
- textlen = strlen (text);
- }
-
- if (text != NULL) {
- string = g_strndup (text, textlen);
- } else { /* empty string */
- string = g_strdup (" ");
- }
- g_strdelimit (string, "\r\t", ' ');
- textlen = strlen (string);
-
- /* FIXME: should we check for UTF-8 here? */
-
- GST_DEBUG ("Rendering '%s'", string);
- pango_layout_set_markup (overlay->layout, string, textlen);
-
- pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect);
- gst_text_overlay_resize_bitmap (overlay, ink_rect.width,
- ink_rect.height + ink_rect.y);
- pango_ft2_render_layout (&overlay->bitmap, overlay->layout, -ink_rect.x, 0);
- overlay->baseline_y = ink_rect.y;
-
- g_free (string);
-
- overlay->need_render = FALSE;
-}
-
-static GstFlowReturn
-gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
- gint xpos, ypos;
-
- video_frame = gst_buffer_make_writable (video_frame);
-
- switch (overlay->halign) {
- case GST_TEXT_OVERLAY_HALIGN_LEFT:
- xpos = overlay->xpad;
- break;
- case GST_TEXT_OVERLAY_HALIGN_CENTER:
- xpos = (overlay->width - overlay->bitmap.width) / 2;
- break;
- case GST_TEXT_OVERLAY_HALIGN_RIGHT:
- xpos = overlay->width - overlay->bitmap.width - overlay->xpad;
- break;
- default:
- xpos = 0;
- }
- xpos += overlay->deltax;
-
-
- switch (overlay->valign) {
- case GST_TEXT_OVERLAY_VALIGN_BOTTOM:
- ypos = overlay->height - overlay->bitmap.rows - overlay->ypad;
- break;
- case GST_TEXT_OVERLAY_VALIGN_BASELINE:
- ypos = overlay->height - (overlay->bitmap.rows + overlay->ypad);
- break;
- case GST_TEXT_OVERLAY_VALIGN_TOP:
- ypos = overlay->ypad;
- break;
- default:
- ypos = overlay->ypad;
- break;
- }
- ypos += overlay->deltay;
-
- /* shaded background box */
- if (overlay->want_shading) {
- gst_text_overlay_shade_y (overlay,
- GST_BUFFER_DATA (video_frame),
- I420_Y_ROWSTRIDE (overlay->width),
- xpos, xpos + overlay->bitmap.width, ypos, ypos + overlay->bitmap.rows);
- }
-
-
- if (overlay->bitmap.buffer) {
- gst_text_overlay_blit_yuv420 (overlay, &overlay->bitmap,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
- }
-
- return gst_pad_push (overlay->srcpad, video_frame);
-}
-
-static GstPadLinkReturn
-gst_text_overlay_text_pad_link (GstPad * pad, GstPad * peer)
-{
- GstTextOverlay *overlay;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- GST_DEBUG_OBJECT (overlay, "Text pad linked");
-
- overlay->text_linked = TRUE;
-
- gst_object_unref (overlay);
-
- return GST_PAD_LINK_OK;
-}
-
-static void
-gst_text_overlay_text_pad_unlink (GstPad * pad)
-{
- GstTextOverlay *overlay;
-
- /* don't use gst_pad_get_parent() here, will deadlock */
- overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
-
- GST_DEBUG_OBJECT (overlay, "Text pad unlinked");
-
- overlay->text_linked = FALSE;
-
- gst_segment_init (&overlay->text_segment, GST_FORMAT_UNDEFINED);
-}
-
-static gboolean
-gst_text_overlay_text_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = FALSE;
- GstTextOverlay *overlay = NULL;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:{
- GstFormat fmt;
- gboolean update;
- gdouble rate, applied_rate;
- gint64 cur, stop, time;
-
- overlay->text_eos = FALSE;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
- &fmt, &cur, &stop, &time);
-
- if (fmt == GST_FORMAT_TIME) {
- GST_OBJECT_LOCK (overlay);
- gst_segment_set_newsegment_full (&overlay->text_segment, update, rate,
- applied_rate, GST_FORMAT_TIME, cur, stop, time);
- GST_DEBUG_OBJECT (overlay, "TEXT SEGMENT now: %" GST_SEGMENT_FORMAT,
- &overlay->text_segment);
- GST_OBJECT_UNLOCK (overlay);
- } else {
- GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL),
- ("received non-TIME newsegment event on text input"));
- }
-
- gst_event_unref (event);
- ret = TRUE;
-
- /* wake up the video chain, it might be waiting for a text buffer or
- * a text segment update */
- GST_OBJECT_LOCK (overlay);
- GST_TEXT_OVERLAY_BROADCAST (overlay);
- GST_OBJECT_UNLOCK (overlay);
- break;
- }
- case GST_EVENT_FLUSH_STOP:
- GST_OBJECT_LOCK (overlay);
- overlay->text_flushing = FALSE;
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
- gst_event_unref (event);
- ret = TRUE;
- break;
- case GST_EVENT_FLUSH_START:
- GST_OBJECT_LOCK (overlay);
- overlay->text_flushing = TRUE;
- GST_TEXT_OVERLAY_BROADCAST (overlay);
- GST_OBJECT_UNLOCK (overlay);
- gst_event_unref (event);
- ret = TRUE;
- break;
- case GST_EVENT_EOS:
- GST_OBJECT_LOCK (overlay);
- overlay->text_flushing = TRUE;
- overlay->text_eos = TRUE;
- GST_INFO_OBJECT (overlay, "EOS");
- /* wake up the video chain, it might be waiting for a text buffer or
- * a text segment update */
- GST_TEXT_OVERLAY_BROADCAST (overlay);
- GST_OBJECT_UNLOCK (overlay);
- gst_event_unref (event);
- ret = TRUE;
- break;
- default:
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (overlay);
-
- return ret;
-}
-
-static gboolean
-gst_text_overlay_video_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = FALSE;
- GstTextOverlay *overlay = NULL;
-
- overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad));
-
- GST_DEBUG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat format;
- gdouble rate;
- gint64 start, stop, time;
- gboolean update;
-
- GST_DEBUG_OBJECT (overlay, "received new segment");
-
- gst_event_parse_new_segment (event, &update, &rate, &format, &start,
- &stop, &time);
-
- if (format == GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (overlay, "VIDEO SEGMENT now: %" GST_SEGMENT_FORMAT,
- overlay->segment);
-
- gst_segment_set_newsegment (overlay->segment, update, rate, format,
- start, stop, time);
- } else {
- GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL),
- ("received non-TIME newsegment event on video input"));
- }
-
- ret = gst_pad_event_default (pad, event);
- break;
- }
- case GST_EVENT_EOS:
- GST_OBJECT_LOCK (overlay);
- overlay->video_flushing = TRUE;
- overlay->text_flushing = TRUE;
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
- ret = gst_pad_event_default (pad, event);
- break;
- case GST_EVENT_FLUSH_START:
- GST_OBJECT_LOCK (overlay);
- overlay->video_flushing = TRUE;
- GST_TEXT_OVERLAY_BROADCAST (overlay);
- GST_OBJECT_UNLOCK (overlay);
- ret = gst_pad_event_default (pad, event);
- break;
- case GST_EVENT_FLUSH_STOP:
- GST_OBJECT_LOCK (overlay);
- overlay->video_flushing = FALSE;
- GST_OBJECT_UNLOCK (overlay);
- ret = gst_pad_event_default (pad, event);
- break;
- default:
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (overlay);
-
- return ret;
-}
-
-/* Called with lock held */
-static void
-gst_text_overlay_pop_text (GstTextOverlay * overlay)
-{
- g_return_if_fail (GST_IS_TEXT_OVERLAY (overlay));
-
- if (overlay->text_buffer) {
- /* update text_segment's last stop */
- if (overlay->text_segment.format == GST_FORMAT_TIME &&
- GST_BUFFER_TIMESTAMP_IS_VALID (overlay->text_buffer)) {
- overlay->text_segment.last_stop =
- GST_BUFFER_TIMESTAMP (overlay->text_buffer);
- if (GST_BUFFER_DURATION_IS_VALID (overlay->text_buffer)) {
- overlay->text_segment.last_stop +=
- GST_BUFFER_DURATION (overlay->text_buffer);
- }
- }
- GST_DEBUG_OBJECT (overlay, "releasing text buffer %p",
- overlay->text_buffer);
- gst_buffer_unref (overlay->text_buffer);
- overlay->text_buffer = NULL;
- }
-
- /* Let the text task know we used that buffer */
- GST_TEXT_OVERLAY_BROADCAST (overlay);
-}
-
-/* We receive text buffers here. If they are out of segment we just ignore them.
- If the buffer is in our segment we keep it internally except if another one
- is already waiting here, in that case we wait that it gets kicked out */
-static GstFlowReturn
-gst_text_overlay_text_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstTextOverlay *overlay = NULL;
- gboolean in_seg = FALSE;
- gint64 clip_start = 0, clip_stop = 0;
-
- overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
-
- GST_OBJECT_LOCK (overlay);
-
- if (overlay->text_eos) {
- GST_OBJECT_UNLOCK (overlay);
- ret = GST_FLOW_UNEXPECTED;
- GST_LOG_OBJECT (overlay, "text EOS");
- goto beach;
- }
-
- if (overlay->text_flushing) {
- GST_OBJECT_UNLOCK (overlay);
- ret = GST_FLOW_WRONG_STATE;
- GST_LOG_OBJECT (overlay, "text flushing");
- goto beach;
- }
-
- GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT " BUFFER: ts=%"
- GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, overlay->segment,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) +
- GST_BUFFER_DURATION (buffer)));
-
- in_seg = gst_segment_clip (overlay->segment, GST_FORMAT_TIME,
- GST_BUFFER_TIMESTAMP (buffer),
- GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
- &clip_start, &clip_stop);
-
- if (in_seg) {
- GST_BUFFER_TIMESTAMP (buffer) = clip_start;
- GST_BUFFER_DURATION (buffer) = clip_stop - clip_start;
-
- /* Wait for the previous buffer to go away */
- while (overlay->text_buffer != NULL) {
- GST_DEBUG ("Pad %s:%s has a buffer queued, waiting",
- GST_DEBUG_PAD_NAME (pad));
- GST_TEXT_OVERLAY_WAIT (overlay);
- GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad));
- if (overlay->text_flushing) {
- GST_OBJECT_UNLOCK (overlay);
- ret = GST_FLOW_WRONG_STATE;
- goto beach;
- }
- }
-
- overlay->text_buffer = buffer;
- /* That's a new text buffer we need to render */
- overlay->need_render = TRUE;
-
- /* in case the video chain is waiting for a text buffer, wake it up */
- GST_TEXT_OVERLAY_BROADCAST (overlay);
- }
-
- GST_OBJECT_UNLOCK (overlay);
-
-beach:
-
- return ret;
-}
-
-static GstFlowReturn
-gst_text_overlay_video_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstTextOverlayClass *klass;
- GstTextOverlay *overlay;
- GstFlowReturn ret = GST_FLOW_OK;
- gboolean in_seg = FALSE;
- gint64 start, stop, clip_start = 0, clip_stop = 0;
- gchar *text = NULL;
-
- overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad));
- klass = GST_TEXT_OVERLAY_GET_CLASS (overlay);
-
- if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
- goto missing_timestamp;
-
- /* ignore buffers that are outside of the current segment */
- start = GST_BUFFER_TIMESTAMP (buffer);
-
- if (!GST_BUFFER_DURATION_IS_VALID (buffer)) {
- stop = GST_CLOCK_TIME_NONE;
- } else {
- stop = start + GST_BUFFER_DURATION (buffer);
- }
-
- GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT " BUFFER: ts=%"
- GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, overlay->segment,
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
- /* segment_clip() will adjust start unconditionally to segment_start if
- * no stop time is provided, so handle this ourselves */
- if (stop == GST_CLOCK_TIME_NONE && start < overlay->segment->start)
- goto out_of_segment;
-
- in_seg = gst_segment_clip (overlay->segment, GST_FORMAT_TIME, start, stop,
- &clip_start, &clip_stop);
-
- if (!in_seg)
- goto out_of_segment;
-
- /* if the buffer is only partially in the segment, fix up stamps */
- if (clip_start != start || (stop != -1 && clip_stop != stop)) {
- GST_DEBUG_OBJECT (overlay, "clipping buffer timestamp/duration to segment");
- buffer = gst_buffer_make_metadata_writable (buffer);
- GST_BUFFER_TIMESTAMP (buffer) = clip_start;
- if (stop != -1)
- GST_BUFFER_DURATION (buffer) = clip_stop - clip_start;
- }
-
- /* now, after we've done the clipping, fix up end time if there's no
- * duration (we only use those estimated values internally though, we
- * don't want to set bogus values on the buffer itself) */
- if (stop == -1) {
- GstStructure *s;
- gint fps_num, fps_denom;
-
- s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0);
- if (gst_structure_get_fraction (s, "framerate", &fps_num, &fps_denom)) {
- GST_DEBUG_OBJECT (overlay, "estimating duration based on framerate");
- stop = start + gst_util_uint64_scale_int (GST_SECOND, fps_denom, fps_num);
- } else {
- GST_WARNING_OBJECT (overlay, "no duration, assuming minimal duration");
- stop = start + 1; /* we need to assume some interval */
- }
- }
-
-wait_for_text_buf:
-
- GST_OBJECT_LOCK (overlay);
-
- if (overlay->video_flushing)
- goto flushing;
-
- if (overlay->silent) {
- GST_OBJECT_UNLOCK (overlay);
- ret = gst_pad_push (overlay->srcpad, buffer);
-
- /* Update last_stop */
- gst_segment_set_last_stop (overlay->segment, GST_FORMAT_TIME, clip_start);
-
- return ret;
- }
-
- /* Text pad not linked, rendering internal text */
- if (!overlay->text_linked) {
- if (klass->get_text) {
- text = klass->get_text (overlay, buffer);
- } else {
- text = g_strdup (overlay->default_text);
- }
-
- GST_LOG_OBJECT (overlay, "Text pad not linked, rendering default "
- "text: '%s'", GST_STR_NULL (text));
-
- GST_OBJECT_UNLOCK (overlay);
-
- if (text != NULL && *text != '\0') {
- /* Render and push */
- gst_text_overlay_render_text (overlay, text, -1);
- ret = gst_text_overlay_push_frame (overlay, buffer);
- } else {
- /* Invalid or empty string */
- ret = gst_pad_push (overlay->srcpad, buffer);
- }
- } else {
- /* Text pad linked, check if we have a text buffer queued */
- if (overlay->text_buffer) {
- gboolean pop_text = FALSE;
- gint64 text_start, text_end;
-
- /* if the text buffer isn't stamped right, pop it off the
- * queue and display it for the current video frame only */
- if (!GST_BUFFER_TIMESTAMP_IS_VALID (overlay->text_buffer) ||
- !GST_BUFFER_DURATION_IS_VALID (overlay->text_buffer)) {
- GST_WARNING_OBJECT (overlay,
- "Got text buffer with invalid timestamp or duration");
- text_start = start;
- text_end = stop;
- pop_text = TRUE;
- } else {
- text_start = GST_BUFFER_TIMESTAMP (overlay->text_buffer);
- text_end = text_start + GST_BUFFER_DURATION (overlay->text_buffer);
- }
-
- GST_LOG_OBJECT (overlay, "T: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
- GST_TIME_ARGS (text_start), GST_TIME_ARGS (text_end));
- GST_LOG_OBJECT (overlay, "V: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
-
- /* Text too old or in the future */
- if (text_end <= start) {
- /* text buffer too old, get rid of it and do nothing */
- GST_LOG_OBJECT (overlay, "text buffer too old, popping");
- pop_text = FALSE;
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
- goto wait_for_text_buf;
- } else if (stop <= text_start) {
- GST_LOG_OBJECT (overlay, "text in future, pushing video buf");
- GST_OBJECT_UNLOCK (overlay);
- /* Push the video frame */
- ret = gst_pad_push (overlay->srcpad, buffer);
- } else {
- gchar *in_text;
- gsize in_size;
-
- in_text = (gchar *) GST_BUFFER_DATA (overlay->text_buffer);
- in_size = GST_BUFFER_SIZE (overlay->text_buffer);
-
- /* g_markup_escape_text() absolutely requires valid UTF8 input, it
- * might crash otherwise. We don't fall back on GST_SUBTITLE_ENCODING
- * here on purpose, this is something that needs fixing upstream */
- if (!g_utf8_validate (in_text, in_size, NULL)) {
- const gchar *end = NULL;
-
- GST_WARNING_OBJECT (overlay, "received invalid UTF-8");
- in_text = g_strndup (in_text, in_size);
- while (!g_utf8_validate (in_text, in_size, &end) && end)
- *((gchar *) end) = '*';
- }
-
- /* Get the string */
- if (overlay->have_pango_markup) {
- text = g_strndup (in_text, in_size);
- } else {
- text = g_markup_escape_text (in_text, in_size);
- }
-
- if (text != NULL && *text != '\0') {
- gint text_len = strlen (text);
-
- while (text_len > 0 && (text[text_len - 1] == '\n' ||
- text[text_len - 1] == '\r')) {
- --text_len;
- }
- GST_DEBUG_OBJECT (overlay, "Rendering text '%*s'", text_len, text);
- gst_text_overlay_render_text (overlay, text, text_len);
- } else {
- GST_DEBUG_OBJECT (overlay, "No text to render (empty buffer)");
- gst_text_overlay_render_text (overlay, " ", 1);
- }
-
- if (in_text != (gchar *) GST_BUFFER_DATA (overlay->text_buffer))
- g_free (in_text);
-
- GST_OBJECT_UNLOCK (overlay);
- ret = gst_text_overlay_push_frame (overlay, buffer);
-
- if (text_end <= stop) {
- GST_LOG_OBJECT (overlay, "text buffer not needed any longer");
- pop_text = TRUE;
- }
- }
- if (pop_text) {
- GST_OBJECT_LOCK (overlay);
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
- }
- } else {
- gboolean wait_for_text_buf = TRUE;
-
- if (overlay->text_eos)
- wait_for_text_buf = FALSE;
-
- /* Text pad linked, but no text buffer available - what now? */
- if (overlay->text_segment.format == GST_FORMAT_TIME) {
- if (GST_BUFFER_TIMESTAMP (buffer) < overlay->text_segment.start ||
- GST_BUFFER_TIMESTAMP (buffer) < overlay->text_segment.last_stop) {
- wait_for_text_buf = FALSE;
- }
- }
-
- if (wait_for_text_buf) {
- GST_DEBUG_OBJECT (overlay, "no text buffer, need to wait for one");
- GST_TEXT_OVERLAY_WAIT (overlay);
- GST_DEBUG_OBJECT (overlay, "resuming");
- GST_OBJECT_UNLOCK (overlay);
- goto wait_for_text_buf;
- } else {
- GST_OBJECT_UNLOCK (overlay);
- GST_LOG_OBJECT (overlay, "no need to wait for a text buffer");
- ret = gst_pad_push (overlay->srcpad, buffer);
- }
- }
- }
-
- g_free (text);
-
- /* Update last_stop */
- gst_segment_set_last_stop (overlay->segment, GST_FORMAT_TIME, clip_start);
-
- return ret;
-
-missing_timestamp:
- {
- GST_WARNING_OBJECT (overlay, "buffer without timestamp, discarding");
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-
-flushing:
- {
- GST_OBJECT_UNLOCK (overlay);
- GST_DEBUG_OBJECT (overlay, "flushing, discarding buffer");
- gst_buffer_unref (buffer);
- return GST_FLOW_WRONG_STATE;
- }
-
-out_of_segment:
- {
- GST_DEBUG_OBJECT (overlay, "buffer out of segment, discarding");
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-}
-
-static GstStateChangeReturn
-gst_text_overlay_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstTextOverlay *overlay = GST_TEXT_OVERLAY (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_OBJECT_LOCK (overlay);
- overlay->text_flushing = TRUE;
- overlay->video_flushing = TRUE;
- /* pop_text will broadcast on the GCond and thus also make the video
- * chain exit if it's waiting for a text buffer */
- gst_text_overlay_pop_text (overlay);
- GST_OBJECT_UNLOCK (overlay);
- break;
- default:
- break;
- }
-
- ret = parent_class->change_state (element, transition);
- if (ret == GST_STATE_CHANGE_FAILURE)
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- GST_OBJECT_LOCK (overlay);
- overlay->text_flushing = FALSE;
- overlay->video_flushing = FALSE;
- GST_OBJECT_UNLOCK (overlay);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "textoverlay", GST_RANK_NONE,
- GST_TYPE_TEXT_OVERLAY) ||
- !gst_element_register (plugin, "timeoverlay", GST_RANK_NONE,
- GST_TYPE_TIME_OVERLAY) ||
- !gst_element_register (plugin, "clockoverlay", GST_RANK_NONE,
- GST_TYPE_CLOCK_OVERLAY) ||
- !gst_element_register (plugin, "textrender", GST_RANK_NONE,
- GST_TYPE_TEXT_RENDER)) {
- return FALSE;
- }
-
- /*texttestsrc_plugin_init(module, plugin); */
-
- GST_DEBUG_CATEGORY_INIT (pango_debug, "pango", 0, "Pango elements");
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
- "pango", "Pango-based text rendering and overlay", plugin_init,
- VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/pango/gsttextoverlay.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-#ifndef __GST_TEXT_OVERLAY_H__
-#define __GST_TEXT_OVERLAY_H__
-
-#include <gst/gst.h>
-#include <pango/pangoft2.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TEXT_OVERLAY (gst_text_overlay_get_type())
-#define GST_TEXT_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
- GST_TYPE_TEXT_OVERLAY, GstTextOverlay))
-#define GST_TEXT_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
- GST_TYPE_TEXT_OVERLAY,GstTextOverlayClass))
-#define GST_TEXT_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
- GST_TYPE_TEXT_OVERLAY, GstTextOverlayClass))
-#define GST_IS_TEXT_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
- GST_TYPE_TEXT_OVERLAY))
-#define GST_IS_TEXT_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
- GST_TYPE_TEXT_OVERLAY))
-
-typedef struct _GstTextOverlay GstTextOverlay;
-typedef struct _GstTextOverlayClass GstTextOverlayClass;
-
-/**
- * GstTextOverlayVAlign:
- * @GST_TEXT_OVERLAY_VALIGN_BASELINE: draw text on the baseline
- * @GST_TEXT_OVERLAY_VALIGN_BOTTOM: draw text on the bottom
- * @GST_TEXT_OVERLAY_VALIGN_TOP: draw test on top
- *
- * Vertical alignment of the text.
- */
-typedef enum {
- GST_TEXT_OVERLAY_VALIGN_BASELINE,
- GST_TEXT_OVERLAY_VALIGN_BOTTOM,
- GST_TEXT_OVERLAY_VALIGN_TOP
-} GstTextOverlayVAlign;
-
-/**
- * GstTextOverlayHAlign:
- * @GST_TEXT_OVERLAY_HALIGN_LEFT: align text left
- * @GST_TEXT_OVERLAY_HALIGN_CENTER: align text center
- * @GST_TEXT_OVERLAY_HALIGN_RIGHT: align text right
- *
- * Horizontal alignment of the text.
- */
-typedef enum {
- GST_TEXT_OVERLAY_HALIGN_LEFT,
- GST_TEXT_OVERLAY_HALIGN_CENTER,
- GST_TEXT_OVERLAY_HALIGN_RIGHT
-} GstTextOverlayHAlign;
-
-/**
- * GstTextOverlayWrapMode:
- * @GST_TEXT_OVERLAY_WRAP_MODE_NONE: no wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_WORD: do word wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_CHAR: do char wrapping
- * @GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR: do word and char wrapping
- *
- * Whether to wrap the text and if so how.
- */
-typedef enum {
- GST_TEXT_OVERLAY_WRAP_MODE_NONE = -1,
- GST_TEXT_OVERLAY_WRAP_MODE_WORD = PANGO_WRAP_WORD,
- GST_TEXT_OVERLAY_WRAP_MODE_CHAR = PANGO_WRAP_CHAR,
- GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR = PANGO_WRAP_WORD_CHAR
-} GstTextOverlayWrapMode;
-
-/**
- * GstTextOverlayLineAlign:
- * @GST_TEXT_OVERLAY_LINE_ALIGN_LEFT: lines are left-aligned
- * @GST_TEXT_OVERLAY_LINE_ALIGN_CENTER: lines are center-aligned
- * @GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT: lines are right-aligned
- *
- * Alignment of text lines relative to each other
- */
-typedef enum {
- GST_TEXT_OVERLAY_LINE_ALIGN_LEFT = PANGO_ALIGN_LEFT,
- GST_TEXT_OVERLAY_LINE_ALIGN_CENTER = PANGO_ALIGN_CENTER,
- GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT = PANGO_ALIGN_RIGHT
-} GstTextOverlayLineAlign;
-
-/**
- * GstTextOverlay:
- *
- * Opaque textoverlay object structure
- */
-struct _GstTextOverlay {
- GstElement element;
-
- GstPad *video_sinkpad;
- GstPad *text_sinkpad;
- GstPad *srcpad;
-
- GstSegment *segment;
- GstSegment text_segment;
- GstBuffer *text_buffer;
- gboolean text_linked;
- gboolean video_flushing;
- gboolean text_flushing;
- gboolean text_eos;
-
- GCond *cond; /* to signal removal of a queued text
- * buffer, arrival of a text buffer,
- * a text segment update, or a change
- * in status (e.g. shutdown, flushing) */
-
- gint width;
- gint height;
- gint fps_n;
- gint fps_d;
-
- GstTextOverlayVAlign valign;
- GstTextOverlayHAlign halign;
- GstTextOverlayWrapMode wrap_mode;
- GstTextOverlayLineAlign line_align;
-
- gint xpad;
- gint ypad;
- gint deltax;
- gint deltay;
- gchar *default_text;
- gboolean want_shading;
- gboolean silent;
-
- PangoLayout *layout;
- FT_Bitmap bitmap;
- gint bitmap_buffer_size;
- gint baseline_y;
-
- gboolean need_render;
-
- gint shading_value; /* for timeoverlay subclass */
-
- gboolean have_pango_markup;
-};
-
-struct _GstTextOverlayClass {
- GstElementClass parent_class;
-
- PangoContext *pango_context;
-
- gchar * (*get_text) (GstTextOverlay *overlay, GstBuffer *video_frame);
-};
-
-GType gst_text_overlay_get_type(void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GST_TEXT_OVERLAY_H */
--- a/gst_plugins_base/ext/pango/gsttextrender.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2003> David Schleef <ds@schleef.org>
- *
- * 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.
- */
-
-
-/**
- * SECTION:element-textrender
- * @see_also: #GstTextOverlay
- *
- * <refsect2>
- * <para>
- * This plugin renders text received on the text sink pad to a video
- * buffer (retaining the alpha channel), so it can later be overlayed
- * on top of video streams using other elements.
- * </para>
- * <para>
- * The text can contain newline characters. (FIXME: What about text
- * wrapping? It does not make sense in this context)
- * </para>
- * <para>
- * Example pipeline:
- * <programlisting>
- * gst-launch -v filesrc location=subtitles.srt ! subparse ! textrender ! xvimagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-
-#include "gsttextrender.h"
-
-GST_DEBUG_CATEGORY_EXTERN (pango_debug);
-#define GST_CAT_DEFAULT pango_debug
-
-static const GstElementDetails text_render_details =
-GST_ELEMENT_DETAILS ("Text renderer",
- "Filter/Editor/Video",
- "Renders a text string to an image bitmap",
- "David Schleef <ds@schleef.org>, "
- "Ronald S. Bultje <rbultje@ronald.bitfreak.net>");
-
-enum
-{
- ARG_0,
- ARG_FONT_DESC
-};
-
-
-static GstStaticPadTemplate src_template_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV"))
- );
-
-static GstStaticPadTemplate sink_template_factory =
- GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("text/x-pango-markup; text/plain")
- );
-
-GST_BOILERPLATE (GstTextRender, gst_text_render, GstElement, GST_TYPE_ELEMENT)
-
- static void gst_text_render_finalize (GObject * object);
- static void gst_text_render_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-
- static void gst_text_render_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_template_factory));
-
- gst_element_class_set_details (element_class, &text_render_details);
-}
-
-static void
-gst_text_render_class_init (GstTextRenderClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_text_render_finalize;
- gobject_class->set_property = gst_text_render_set_property;
-
- klass->pango_context = pango_ft2_get_context (72, 72);
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FONT_DESC,
- g_param_spec_string ("font-desc", "font description",
- "Pango font description of font "
- "to be used for rendering. "
- "See documentation of "
- "pango_font_description_from_string"
- " for syntax.", "", G_PARAM_WRITABLE));
-}
-
-
-static void
-resize_bitmap (GstTextRender * render, gint width, gint height)
-{
- FT_Bitmap *bitmap = &render->bitmap;
- gint pitch = (width | 3) + 1;
- gint size = pitch * height;
-
- /* no need to keep reallocating; just keep the maximum size so far */
- if (size <= render->bitmap_buffer_size) {
- bitmap->rows = height;
- bitmap->width = width;
- bitmap->pitch = pitch;
- memset (bitmap->buffer, 0, render->bitmap_buffer_size);
- return;
- }
- if (!bitmap->buffer) {
- /* initialize */
- bitmap->pixel_mode = ft_pixel_mode_grays;
- bitmap->num_grays = 256;
- }
- if (bitmap->buffer)
- bitmap->buffer = g_realloc (bitmap->buffer, size);
- else
- bitmap->buffer = g_malloc (size);
- bitmap->rows = height;
- bitmap->width = width;
- bitmap->pitch = pitch;
- memset (bitmap->buffer, 0, size);
- render->bitmap_buffer_size = size;
-}
-
-static void
-gst_text_render_render_text (GstTextRender * render)
-{
- PangoRectangle ink_rect, logical_rect;
-
- pango_layout_get_pixel_extents (render->layout, &ink_rect, &logical_rect);
- resize_bitmap (render, ink_rect.width, ink_rect.height + ink_rect.y);
- pango_ft2_render_layout (&render->bitmap, render->layout, -ink_rect.x, 0);
- render->baseline_y = ink_rect.y;
-}
-
-static gboolean
-gst_text_render_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
- GstStructure *structure;
- gboolean ret = FALSE;
- gint width = 0, height = 0;
-
- structure = gst_caps_get_structure (caps, 0);
- gst_structure_get_int (structure, "width", &width);
- gst_structure_get_int (structure, "height", &height);
-
- GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps);
-
- if (width >= render->bitmap.width && height >= render->bitmap.rows) {
- render->width = width;
- render->height = height;
- ret = TRUE;
- }
-
- gst_object_unref (render);
- return ret;
-}
-
-static void
-gst_text_render_fixate_caps (GstPad * pad, GstCaps * caps)
-{
- GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
- GstStructure *s = gst_caps_get_structure (caps, 0);
-
- GST_DEBUG ("Fixating caps %" GST_PTR_FORMAT, caps);
- gst_structure_fixate_field_nearest_int (s, "width", render->bitmap.width);
- gst_structure_fixate_field_nearest_int (s, "height", render->bitmap.rows);
- GST_DEBUG ("Fixated to %" GST_PTR_FORMAT, caps);
-
- gst_object_unref (render);
-}
-
-static void
-gst_text_renderer_bitmap_to_ayuv (GstTextRender * render, FT_Bitmap * bitmap,
- guchar * pixbuf)
-{
- int y; /* text bitmap coordinates */
- int rowinc, bit_rowinc;
- guchar *p, *bitp;
- guchar v;
-
- rowinc = render->width - bitmap->width;
- bit_rowinc = bitmap->pitch - bitmap->width;
-
- bitp = bitmap->buffer;
- p = pixbuf;
-
- for (y = 0; y < bitmap->rows; y++) {
- int n;
-
- for (n = bitmap->width; n > 0; --n) {
- v = *bitp;
- if (v) {
- p[0] = v;
- p[1] = 255;
- p[2] = 0x80;
- p[3] = 0x80;
- }
- p += 4;
- bitp++;
- }
- p += rowinc * 4;
- bitp += bit_rowinc;
- }
-}
-
-
-static GstFlowReturn
-gst_text_render_chain (GstPad * pad, GstBuffer * inbuf)
-{
- GstTextRender *render;
- GstFlowReturn ret;
- GstBuffer *outbuf;
- GstCaps *caps = NULL;
- guint8 *data = GST_BUFFER_DATA (inbuf);
- guint size = GST_BUFFER_SIZE (inbuf);
- gint n;
-
- render = GST_TEXT_RENDER (gst_pad_get_parent (pad));
-
- /* somehow pango barfs over "\0" buffers... */
- while (size > 0 &&
- (data[size - 1] == '\r' ||
- data[size - 1] == '\n' || data[size - 1] == '\0')) {
- size--;
- }
-
- /* render text */
- GST_DEBUG ("rendering '%*s'", size, data);
- pango_layout_set_markup (render->layout, (gchar *) data, size);
- gst_text_render_render_text (render);
-
- caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC,
- GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), "width", G_TYPE_INT,
- render->bitmap.width, "height", G_TYPE_INT, render->bitmap.rows,
- "framerate", GST_TYPE_FRACTION, 1, 1, NULL);
-
- if (!gst_pad_set_caps (render->srcpad, caps)) {
- gst_caps_unref (caps);
- GST_ELEMENT_ERROR (render, CORE, NEGOTIATION, (NULL), (NULL));
- ret = GST_FLOW_ERROR;
- goto done;
- }
-
- GST_DEBUG ("Allocating AYUV buffer WxH = %dx%d", render->width,
- render->height);
- ret =
- gst_pad_alloc_buffer_and_set_caps (render->srcpad, GST_BUFFER_OFFSET_NONE,
- render->width * render->height * 4, caps, &outbuf);
-
- if (ret != GST_FLOW_OK)
- goto done;
-
- gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS);
- data = GST_BUFFER_DATA (outbuf);
-
- for (n = 0; n < render->width * render->height; n++) {
- data[n * 4] = 0;
- data[n * 4 + 1] = 0;
- data[n * 4 + 2] = data[n * 4 + 3] = 128;
- }
-
- if (render->bitmap.buffer) {
- gst_text_renderer_bitmap_to_ayuv (render, &render->bitmap, data);
- }
-
- ret = gst_pad_push (render->srcpad, outbuf);
-
-done:
- if (caps)
- gst_caps_unref (caps);
- gst_buffer_unref (inbuf);
- gst_object_unref (render);
- return ret;
-}
-
-static void
-gst_text_render_finalize (GObject * object)
-{
- GstTextRender *render = GST_TEXT_RENDER (object);
-
- g_free (render->bitmap.buffer);
-
- if (render->layout)
- g_object_unref (render->layout);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_text_render_init (GstTextRender * render, GstTextRenderClass * klass)
-{
- GstPadTemplate *template;
-
- /* sink */
- template = gst_static_pad_template_get (&sink_template_factory);
- render->sinkpad = gst_pad_new_from_template (template, "sink");
- gst_object_unref (template);
- gst_pad_set_chain_function (render->sinkpad,
- GST_DEBUG_FUNCPTR (gst_text_render_chain));
- gst_element_add_pad (GST_ELEMENT (render), render->sinkpad);
-
- /* source */
- template = gst_static_pad_template_get (&src_template_factory);
- render->srcpad = gst_pad_new_from_template (template, "src");
- gst_object_unref (template);
- gst_pad_set_fixatecaps_function (render->srcpad,
- GST_DEBUG_FUNCPTR (gst_text_render_fixate_caps));
- gst_pad_set_setcaps_function (render->srcpad,
- GST_DEBUG_FUNCPTR (gst_text_render_setcaps));
- gst_element_add_pad (GST_ELEMENT (render), render->srcpad);
-
- render->layout =
- pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context);
- memset (&render->bitmap, 0, sizeof (render->bitmap));
-}
-
-static void
-gst_text_render_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTextRender *render = GST_TEXT_RENDER (object);
-
- switch (prop_id) {
- case ARG_FONT_DESC:
- {
- PangoFontDescription *desc;
-
- desc = pango_font_description_from_string (g_value_get_string (value));
- if (desc) {
- GST_LOG ("font description set: %s", g_value_get_string (value));
- GST_OBJECT_LOCK (render);
- pango_layout_set_font_description (render->layout, desc);
- pango_font_description_free (desc);
- gst_text_render_render_text (render);
- GST_OBJECT_UNLOCK (render);
- } else {
- GST_WARNING ("font description parse failed: %s",
- g_value_get_string (value));
- }
- break;
- }
-
- default:
- break;
- }
-}
--- a/gst_plugins_base/ext/pango/gsttextrender.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#ifndef __GST_TEXT_RENDER_H__
-#define __GST_TEXT_RENDER_H__
-
-#include <gst/gst.h>
-#include <pango/pangoft2.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TEXT_RENDER (gst_text_render_get_type())
-#define GST_TEXT_RENDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
- GST_TYPE_TEXT_RENDER, GstTextRender))
-#define GST_TEXT_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
- GST_TYPE_TEXT_RENDER, GstTextRenderClass))
-#define GST_TEXT_RENDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
- GST_TYPE_TEXT_RENDER, GstTextRenderClass))
-#define GST_IS_TEXT_RENDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
- GST_TYPE_TEXT_RENDER))
-#define GST_IS_TEXT_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
- GST_TYPE_TEXT_RENDER))
-
-typedef struct _GstTextRender GstTextRender;
-typedef struct _GstTextRenderClass GstTextRenderClass;
-
-/**
- * GstTextRender:
- *
- * Opaque textrender data structure.
- */
-struct _GstTextRender {
- GstElement element;
-
- GstPad *sinkpad, *srcpad;
- gint width;
- gint height;
- PangoLayout *layout;
- FT_Bitmap bitmap;
- gint bitmap_buffer_size;
- gint baseline_y;
-};
-
-struct _GstTextRenderClass {
- GstElementClass parent_class;
-
- PangoContext *pango_context;
-};
-
-GType gst_text_render_get_type(void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GST_TEXT_RENDER_H */
--- a/gst_plugins_base/ext/pango/gsttimeoverlay.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-timeoverlay
- * @see_also: #GstTextOverlay, #GstClockOverlay
- *
- * <refsect2>
- * <para>
- * This element overlays the buffer time stamps of a video stream on
- * top of itself. You can position the text and configure the font details
- * using the properties of the #GstTextOverlay class. By default, the
- * time stamp is displayed in the top left corner of the picture, with some
- * padding to the left and to the top.
- * </para>
- * <para>
- * Here is a simple pipeline that displays the time stamps in the top left
- * corner of the video picture:
- * <programlisting>
- * gst-launch -v videotestsrc ! timeoverlay ! xvimagesink
- * </programlisting>
- * </para>
- * <para>
- * Here is another pipeline that displays the time stamps with some leading
- * text in the bottom right corner of the video picture, with the background
- * of the text being shaded in order to make it more legible on top of a
- * bright video background:
- * <programlisting>
- * gst-launch -v videotestsrc ! timeoverlay halign=right valign=bottom text="Stream time:" shaded-background=true ! xvimagesink
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/video/video.h>
-
-#include <gsttimeoverlay.h>
-
-static const GstElementDetails time_overlay_details =
-GST_ELEMENT_DETAILS ("Time overlay",
- "Filter/Editor/Video",
- "Overlays buffer time stamps on a video stream",
- "Tim-Philipp Müller <tim@centricular.net>");
-
-GST_BOILERPLATE (GstTimeOverlay, gst_time_overlay, GstTextOverlay,
- GST_TYPE_TEXT_OVERLAY)
-
- static void gst_time_overlay_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &time_overlay_details);
-}
-
-static gchar *
-gst_time_overlay_render_time (GstTimeOverlay * overlay, GstClockTime time)
-{
- guint hours, mins, secs, msecs;
-
- if (!GST_CLOCK_TIME_IS_VALID (time))
- return g_strdup ("");
-
- hours = (guint) (time / (GST_SECOND * 60 * 60));
- mins = (guint) ((time / (GST_SECOND * 60)) % 60);
- secs = (guint) ((time / GST_SECOND) % 60);
- msecs = (guint) ((time % GST_SECOND) / (1000 * 1000));
-
- return g_strdup_printf ("%u:%02u:%02u.%03u", hours, mins, secs, msecs);
-}
-
-/* Called with lock held */
-static gchar *
-gst_time_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame)
-{
- GstClockTime time = GST_BUFFER_TIMESTAMP (video_frame);
- gchar *time_str, *txt, *ret;
-
- overlay->need_render = TRUE;
-
- if (!GST_CLOCK_TIME_IS_VALID (time)) {
- GST_DEBUG ("buffer without valid timestamp");
- return g_strdup ("");
- }
-
- GST_DEBUG ("buffer with timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (time));
-
- txt = g_strdup (overlay->default_text);
-
- time_str = gst_time_overlay_render_time (GST_TIME_OVERLAY (overlay), time);
- if (txt != NULL && *txt != '\0') {
- ret = g_strdup_printf ("%s %s", txt, time_str);
- } else {
- ret = time_str;
- time_str = NULL;
- }
-
- g_free (txt);
- g_free (time_str);
-
- return ret;
-}
-
-static void
-gst_time_overlay_class_init (GstTimeOverlayClass * klass)
-{
- GstTextOverlayClass *gsttextoverlay_class;
-
- gsttextoverlay_class = (GstTextOverlayClass *) klass;
-
- gsttextoverlay_class->get_text = gst_time_overlay_get_text;
-}
-
-static void
-gst_time_overlay_init (GstTimeOverlay * overlay, GstTimeOverlayClass * klass)
-{
- PangoFontDescription *font_description;
- GstTextOverlay *textoverlay;
- PangoContext *context;
-
- textoverlay = GST_TEXT_OVERLAY (overlay);
-
- context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context;
-
- pango_context_set_language (context, pango_language_from_string ("en_US"));
- pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
-
- font_description = pango_font_description_new ();
- pango_font_description_set_family_static (font_description, "Monospace");
- pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
- pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
- pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
- pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
- pango_font_description_set_size (font_description, 18 * PANGO_SCALE);
- pango_context_set_font_description (context, font_description);
- pango_font_description_free (font_description);
-
- textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP;
- textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT;
-}
--- a/gst_plugins_base/ext/pango/gsttimeoverlay.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2005> 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-#ifndef __GST_TIME_OVERLAY_H__
-#define __GST_TIME_OVERLAY_H__
-
-#include "gsttextoverlay.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_TIME_OVERLAY \
- (gst_time_overlay_get_type())
-#define GST_TIME_OVERLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TIME_OVERLAY,GstTimeOverlay))
-#define GST_TIME_OVERLAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TIME_OVERLAY,GstTimeOverlayClass))
-#define GST_IS_TIME_OVERLAY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIME_OVERLAY))
-#define GST_IS_TIME_OVERLAY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TIME_OVERLAY))
-
-typedef struct _GstTimeOverlay GstTimeOverlay;
-typedef struct _GstTimeOverlayClass GstTimeOverlayClass;
-
-/**
- * GstTimeOverlay:
- *
- * Opaque timeoverlay data structure.
- */
-struct _GstTimeOverlay {
- GstTextOverlay textoverlay;
-};
-
-struct _GstTimeOverlayClass {
- GstTextOverlayClass parent_class;
-};
-
-GType gst_time_overlay_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_TIME_OVERLAY_H__ */
-
--- a/gst_plugins_base/ext/theora/gsttheoradec.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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 __GST_THEORADEC_H__
-#define __GST_THEORADEC_H__
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-#include <string.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_DEC \
- (gst_theora_dec_get_type())
-#define GST_THEORA_DEC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_DEC,GstTheoraDec))
-#define GST_THEORA_DEC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_DEC,GstTheoraDecClass))
-#define GST_IS_THEORA_DEC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_DEC))
-#define GST_IS_THEORA_DEC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_DEC))
-
-typedef struct _GstTheoraDec GstTheoraDec;
-typedef struct _GstTheoraDecClass GstTheoraDecClass;
-
-/**
- * GstTheoraDec:
- *
- * Opaque object data structure.
- */
-struct _GstTheoraDec
-{
- GstElement element;
-
- /* Pads */
- GstPad *sinkpad;
- GstPad *srcpad;
-
- /* theora decoder state */
- theora_state state;
- theora_info info;
- theora_comment comment;
-
- gboolean have_header;
- gboolean sent_newsegment;
- gboolean is_old_bitstream;
- guint64 granulepos;
- guint64 granule_shift;
-
- GstClockTime last_timestamp;
- guint64 frame_nr; /* unused */
- gboolean need_keyframe;
- gint width, height;
- gint offset_x, offset_y;
-
- gboolean crop;
-
- /* list of buffers that need timestamps */
- GList *queued;
- /* list of raw output buffers */
- GList *output;
- /* gather/decode queues for reverse playback */
- GList *gather;
- GList *decode;
-
- GstTagList *tags;
-
- /* segment info */ /* with STREAM_LOCK */
- GstSegment segment;
- gboolean discont;
-
- /* QoS stuff */ /* with LOCK*/
- gdouble proportion;
- GstClockTime earliest_time;
-};
-
-struct _GstTheoraDecClass
-{
- GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_THEORADEC_H__ */
--- a/gst_plugins_base/ext/theora/gsttheoraenc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.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 __GST_THEORAENC_H__
-#define __GST_THEORAENC_H__
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_ENC \
- (gst_theora_enc_get_type())
-#define GST_THEORA_ENC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_ENC,GstTheoraEnc))
-#define GST_THEORA_ENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_ENC,GstTheoraEncClass))
-#define GST_IS_THEORA_ENC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_ENC))
-#define GST_IS_THEORA_ENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_ENC))
-
-typedef struct _GstTheoraEnc GstTheoraEnc;
-typedef struct _GstTheoraEncClass GstTheoraEncClass;
-
-/**
- * GstTheoraEncBorderMode:
- * @BORDER_NONE: no border
- * @BORDER_BLACK: black border
- * @BORDER_MIRROR: Mirror image in border
- *
- * Border color to add when sizes not multiple of 16.
- */
-typedef enum
-{
- BORDER_NONE,
- BORDER_BLACK,
- BORDER_MIRROR
-}
-GstTheoraEncBorderMode;
-
-/**
- * GstTheoraEnc:
- *
- * Opaque data structure.
- */
-struct _GstTheoraEnc
-{
- GstElement element;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- ogg_stream_state to;
-
- theora_state state;
- theora_info info;
- theora_comment comment;
- gboolean initialised;
-
- gboolean center;
- GstTheoraEncBorderMode border;
-
- gint video_bitrate; /* bitrate target for Theora video */
- gint video_quality; /* Theora quality selector 0 = low, 63 = high */
- gboolean quick;
- gboolean keyframe_auto;
- gint keyframe_freq;
- gint keyframe_force;
- gint keyframe_threshold;
- gint keyframe_mindistance;
- gint noise_sensitivity;
- gint sharpness;
-
- gint info_width, info_height;
- gint width, height;
- gint offset_x, offset_y;
- gint fps_n, fps_d;
- GstClockTime next_ts;
-
- GstClockTime expected_ts;
- gboolean next_discont;
-
- guint packetno;
- guint64 bytes_out;
- guint64 granulepos_offset;
- guint64 timestamp_offset;
- gint granule_shift;
-};
-
-struct _GstTheoraEncClass
-{
- GstElementClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GST_THEORAENC_H__ */
-
--- a/gst_plugins_base/ext/theora/gsttheoraparse.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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 __GST_THEORA_PARSE_H__
-#define __GST_THEORA_PARSE_H__
-
-
-#include <gst/gst.h>
-#include <theora/theora.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_THEORA_PARSE \
- (gst_theora_parse_get_type())
-#define GST_THEORA_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_PARSE,GstTheoraParse))
-#define GST_THEORA_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_PARSE,GstTheoraParseClass))
-#define GST_IS_THEORA_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_PARSE))
-#define GST_IS_THEORA_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_PARSE))
-
-typedef struct _GstTheoraParse GstTheoraParse;
-typedef struct _GstTheoraParseClass GstTheoraParseClass;
-
-/**
- * GstTheoraParse:
- *
- * Opaque data structure.
- */
-struct _GstTheoraParse {
- GstElement element;
-
- GstPad * sinkpad;
- GstPad * srcpad;
-
- guint packetno;
- gboolean send_streamheader;
- gboolean streamheader_received;
- gboolean is_old_bitstream;
- GstBuffer * streamheader[3];
-
- GQueue * event_queue;
- GQueue * buffer_queue;
-
- theora_info info;
- theora_comment comment;
-
- gint64 prev_frame;
- gint64 prev_keyframe;
- guint32 fps_n;
- guint32 fps_d;
- gint shift;
- gint64 granule_offset;
-
- GstClockTime *times;
- gint npairs;
-};
-
-struct _GstTheoraParseClass {
- GstElementClass parent_class;
-};
-
-GType gst_theora_parse_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_THEORA_PARSE_H__ */
--- a/gst_plugins_base/ext/theora/theora.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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 <gst/gst.h>
-
-extern GType gst_theora_dec_get_type (void);
-extern GType gst_theora_enc_get_type (void);
-extern GType gst_theora_parse_get_type (void);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "theoradec", GST_RANK_PRIMARY,
- gst_theora_dec_get_type ()))
- return FALSE;
-
- if (!gst_element_register (plugin, "theoraenc", GST_RANK_NONE,
- gst_theora_enc_get_type ()))
- return FALSE;
-
- if (!gst_element_register (plugin, "theoraparse", GST_RANK_NONE,
- gst_theora_parse_get_type ()))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "theora",
- "Theora plugin library",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/theora/theoradec.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1547 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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.
- */
-
-/**
- * SECTION:element-theoradec
- * @see_also: theoraenc, oggdemux
- *
- * <refsect2>
- * <para>
- * This element decodes theora streams into raw video
- * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
- * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>, based on the VP3 codec.
- * </para>
- * <para>
- * </para>
- * <title>Example pipeline</title>
- * <programlisting>
- * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! xvimagesink
- * </programlisting>
- * This example pipeline will decode an ogg stream and decodes the theora video. Refer to
- * the theoraenc example to create the ogg file.
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gsttheoradec.h"
-#include <gst/tag/tag.h>
-
-#define GST_CAT_DEFAULT theoradec_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-#define THEORA_DEF_CROP TRUE
-enum
-{
- ARG_0,
- ARG_CROP
-};
-
-static const GstElementDetails theora_dec_details =
-GST_ELEMENT_DETAILS ("Theora video decoder",
- "Codec/Decoder/Video",
- "decode raw theora streams to raw YUV video",
- "Benjamin Otte <in7y118@public.uni-hamburg.de>, "
- "Wim Taymans <wim@fluendo.com>");
-
-static GstStaticPadTemplate theora_dec_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-yuv, "
- "format = (fourcc) I420, "
- "framerate = (fraction) [0/1, MAX], "
- "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
- );
-
-static GstStaticPadTemplate theora_dec_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-theora")
- );
-
-GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
-
-static void theora_dec_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void theora_dec_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-
-static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_dec_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event);
-static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query);
-static gboolean theora_dec_src_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value);
-static gboolean theora_dec_sink_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value);
-static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
-
-#if 0
-static const GstFormat *theora_get_formats (GstPad * pad);
-#endif
-#if 0
-static const GstEventMask *theora_get_event_masks (GstPad * pad);
-#endif
-static const GstQueryType *theora_get_query_types (GstPad * pad);
-
-
-static void
-gst_theora_dec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_dec_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_dec_sink_factory));
- gst_element_class_set_details (element_class, &theora_dec_details);
-}
-
-static void
-gst_theora_dec_class_init (GstTheoraDecClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->set_property = theora_dec_set_property;
- gobject_class->get_property = theora_dec_get_property;
-
- g_object_class_install_property (gobject_class, ARG_CROP,
- g_param_spec_boolean ("crop", "Crop",
- "Crop the image to the visible region", THEORA_DEF_CROP,
- (GParamFlags) G_PARAM_READWRITE));
-
- gstelement_class->change_state = theora_dec_change_state;
-
- GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
-}
-
-static void
-gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
-{
- dec->sinkpad =
- gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink");
- gst_pad_set_query_function (dec->sinkpad, theora_dec_sink_query);
- gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event);
- gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain);
- gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
-
- dec->srcpad =
- gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
- gst_pad_set_event_function (dec->srcpad, theora_dec_src_event);
- gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types);
- gst_pad_set_query_function (dec->srcpad, theora_dec_src_query);
- gst_pad_use_fixed_caps (dec->srcpad);
-
- gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
-
- dec->crop = THEORA_DEF_CROP;
- dec->gather = NULL;
- dec->decode = NULL;
- dec->queued = NULL;
-}
-
-static void
-gst_theora_dec_reset (GstTheoraDec * dec)
-{
- dec->need_keyframe = TRUE;
- dec->sent_newsegment = FALSE;
- dec->last_timestamp = -1;
- dec->granulepos = -1;
- dec->discont = TRUE;
- dec->frame_nr = -1;
- gst_segment_init (&dec->segment, GST_FORMAT_TIME);
-
- GST_OBJECT_LOCK (dec);
- dec->proportion = 1.0;
- dec->earliest_time = -1;
- GST_OBJECT_UNLOCK (dec);
-
- g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->queued);
- dec->queued = NULL;
- g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->gather);
- dec->gather = NULL;
- g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->decode);
- dec->decode = NULL;
-
- if (dec->tags) {
- gst_tag_list_free (dec->tags);
- dec->tags = NULL;
- }
-}
-
-static int
-_theora_ilog (unsigned int v)
-{
- int ret = 0;
-
- while (v) {
- ret++;
- v >>= 1;
- }
- return (ret);
-}
-
-/* Return the frame number (starting from zero) corresponding to this
- * granulepos */
-static gint64
-_theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
-{
- guint ilog;
- gint framenum;
-
- if (granulepos == -1)
- return -1;
-
- ilog = dec->granule_shift;
-
- /* granulepos is last ilog bits for counting pframes since last iframe and
- * bits in front of that for the framenumber of the last iframe. */
- framenum = granulepos >> ilog;
- framenum += granulepos - (framenum << ilog);
-
- /* This is 0-based for old bitstreams, 1-based for new. Fix up. */
- if (!dec->is_old_bitstream)
- framenum -= 1;
-
- GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
-
- return framenum;
-}
-
-/* Return the frame start time corresponding to this granulepos */
-static GstClockTime
-_theora_granule_start_time (GstTheoraDec * dec, gint64 granulepos)
-{
- gint64 framecount;
-
- /* invalid granule results in invalid time */
- if (granulepos == -1)
- return -1;
-
- /* get framecount */
- framecount = _theora_granule_frame (dec, granulepos);
-
- return gst_util_uint64_scale_int (framecount * GST_SECOND,
- dec->info.fps_denominator, dec->info.fps_numerator);
-}
-
-static gint64
-_inc_granulepos (GstTheoraDec * dec, gint64 granulepos)
-{
- gint framecount;
-
- if (granulepos == -1)
- return -1;
-
- framecount = _theora_granule_frame (dec, granulepos);
-
- return (framecount + 1 +
- (dec->is_old_bitstream ? 0 : 1)) << dec->granule_shift;
-}
-
-#if 0
-static const GstFormat *
-theora_get_formats (GstPad * pad)
-{
- static GstFormat src_formats[] = {
- GST_FORMAT_DEFAULT, /* frames in this case */
- GST_FORMAT_TIME,
- GST_FORMAT_BYTES,
- 0
- };
- static GstFormat sink_formats[] = {
- GST_FORMAT_DEFAULT,
- GST_FORMAT_TIME,
- 0
- };
-
- return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
-}
-#endif
-
-#if 0
-static const GstEventMask *
-theora_get_event_masks (GstPad * pad)
-{
- static const GstEventMask theora_src_event_masks[] = {
- {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
- {0,}
- };
-
- return theora_src_event_masks;
-}
-#endif
-
-static const GstQueryType *
-theora_get_query_types (GstPad * pad)
-{
- static const GstQueryType theora_src_query_types[] = {
- GST_QUERY_POSITION,
- GST_QUERY_DURATION,
- GST_QUERY_CONVERT,
- 0
- };
-
- return theora_src_query_types;
-}
-
-
-static gboolean
-theora_dec_src_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstTheoraDec *dec;
- guint64 scale = 1;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- /* we need the info part before we can done something */
- if (!dec->have_header)
- goto no_header;
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- *dest_value = gst_util_uint64_scale_int (src_value, 2,
- dec->info.height * dec->info.width * 3);
- break;
- case GST_FORMAT_TIME:
- /* seems like a rather silly conversion, implement me if you like */
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- scale = 3 * (dec->info.width * dec->info.height) / 2;
- case GST_FORMAT_DEFAULT:
- *dest_value = scale * gst_util_uint64_scale (src_value,
- dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = gst_util_uint64_scale (src_value,
- GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
- break;
- case GST_FORMAT_BYTES:
- *dest_value = gst_util_uint64_scale_int (src_value,
- 3 * dec->info.width * dec->info.height, 2);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-done:
- gst_object_unref (dec);
- return res;
-
- /* ERRORS */
-no_header:
- {
- GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-theora_dec_sink_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstTheoraDec *dec;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- /* we need the info part before we can done something */
- if (!dec->have_header)
- goto no_header;
-
- switch (src_format) {
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = _theora_granule_start_time (dec, src_value);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- {
- guint rest;
-
- /* framecount */
- *dest_value = gst_util_uint64_scale (src_value,
- dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator);
-
- /* funny way of calculating granulepos in theora */
- rest = *dest_value / dec->info.keyframe_frequency_force;
- *dest_value -= rest;
- *dest_value <<= dec->granule_shift;
- *dest_value += rest;
- break;
- }
- default:
- res = FALSE;
- break;
- }
- break;
- default:
- res = FALSE;
- }
-done:
- gst_object_unref (dec);
- return res;
-
- /* ERRORS */
-no_header:
- {
- GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-theora_dec_src_query (GstPad * pad, GstQuery * query)
-{
- GstTheoraDec *dec;
-
- gboolean res = FALSE;
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 granulepos, value;
- GstFormat my_format, format;
- gint64 time;
-
- /* we can convert a granule position to everything */
- granulepos = dec->granulepos;
-
- GST_LOG_OBJECT (dec,
- "query %p: we have current granule: %lld", query, granulepos);
-
- /* parse format */
- gst_query_parse_position (query, &format, NULL);
-
- /* and convert to the final format in two steps with time as the
- * intermediate step */
- my_format = GST_FORMAT_TIME;
- if (!(res =
- theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
- granulepos, &my_format, &time)))
- goto error;
-
- time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
-
- GST_LOG_OBJECT (dec,
- "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
-
- if (!(res =
- theora_dec_src_convert (pad, my_format, time, &format, &value)))
- goto error;
-
- gst_query_set_position (query, format, value);
-
- GST_LOG_OBJECT (dec,
- "query %p: we return %lld (format %u)", query, value, format);
-
- break;
- }
- case GST_QUERY_DURATION:
- {
- GstPad *peer;
-
- if (!(peer = gst_pad_get_peer (dec->sinkpad)))
- goto error;
-
- /* forward to peer for total */
- res = gst_pad_query (peer, query);
- gst_object_unref (peer);
- if (!res)
- goto error;
-
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
-
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (dec, "query failed");
- goto done;
- }
-}
-
-static gboolean
-theora_dec_sink_query (GstPad * pad, GstQuery * query)
-{
- gboolean res = FALSE;
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
-
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
-error:
- return res;
-}
-
-static gboolean
-theora_dec_src_event (GstPad * pad, GstEvent * event)
-{
- gboolean res = TRUE;
- GstTheoraDec *dec;
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- {
- GstFormat format, tformat;
- gdouble rate;
- GstEvent *real_seek;
- GstSeekFlags flags;
- GstSeekType cur_type, stop_type;
- gint64 cur, stop;
- gint64 tcur, tstop;
-
- gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
- &stop_type, &stop);
- gst_event_unref (event);
-
- /* we have to ask our peer to seek to time here as we know
- * nothing about how to generate a granulepos from the src
- * formats or anything.
- *
- * First bring the requested format to time
- */
- tformat = GST_FORMAT_TIME;
- if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
- goto convert_error;
- if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
- goto convert_error;
-
- /* then seek with time on the peer */
- real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
- flags, cur_type, tcur, stop_type, tstop);
-
- res = gst_pad_push_event (dec->sinkpad, real_seek);
- break;
- }
- case GST_EVENT_QOS:
- {
- gdouble proportion;
- GstClockTimeDiff diff;
- GstClockTime timestamp;
-
- gst_event_parse_qos (event, &proportion, &diff, ×tamp);
-
- /* we cannot randomly skip frame decoding since we don't have
- * B frames. we can however use the timestamp and diff to not
- * push late frames. This would at least save us the time to
- * crop/memcpy the data. */
- GST_OBJECT_LOCK (dec);
- dec->proportion = proportion;
- dec->earliest_time = timestamp + diff;
- GST_OBJECT_UNLOCK (dec);
-
- GST_DEBUG_OBJECT (dec, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT,
- GST_TIME_ARGS (timestamp), diff);
-
- res = gst_pad_push_event (dec->sinkpad, event);
- break;
- }
- default:
- res = gst_pad_push_event (dec->sinkpad, event);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-convert_error:
- {
- GST_DEBUG_OBJECT (dec, "could not convert format");
- goto done;
- }
-}
-
-static gboolean
-theora_dec_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = FALSE;
- GstTheoraDec *dec;
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (dec, "handling event");
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_FLUSH_STOP:
- gst_theora_dec_reset (dec);
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_EOS:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_NEWSEGMENT:
- {
- gboolean update;
- GstFormat format;
- gdouble rate, arate;
- gint64 start, stop, time;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
- &start, &stop, &time);
-
- /* we need TIME format */
- if (format != GST_FORMAT_TIME)
- goto newseg_wrong_format;
-
- /* now configure the values */
- gst_segment_set_newsegment_full (&dec->segment, update,
- rate, arate, format, start, stop, time);
-
- /* We don't forward this unless/until the decoder is initialised */
- if (dec->have_header) {
- ret = gst_pad_push_event (dec->srcpad, event);
- dec->sent_newsegment = TRUE;
- } else {
- gst_event_unref (event);
- ret = TRUE;
- }
- break;
- }
- default:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return ret;
-
- /* ERRORS */
-newseg_wrong_format:
- {
- GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
- gst_event_unref (event);
- goto done;
- }
-}
-
-static GstFlowReturn
-theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
- gchar *encoder = NULL;
- GstBuffer *buf;
- GstTagList *list;
-
- GST_DEBUG_OBJECT (dec, "parsing comment packet");
-
- buf = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
-
- list =
- gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
- &encoder);
-
- gst_buffer_unref (buf);
-
- if (!list) {
- GST_ERROR_OBJECT (dec, "couldn't decode comments");
- list = gst_tag_list_new ();
- }
- if (encoder) {
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- GST_TAG_ENCODER, encoder, NULL);
- g_free (encoder);
- }
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- GST_TAG_ENCODER_VERSION, dec->info.version_major,
- GST_TAG_VIDEO_CODEC, "Theora", NULL);
-
- if (dec->info.target_bitrate > 0) {
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- GST_TAG_BITRATE, dec->info.target_bitrate,
- GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate, NULL);
- }
-
- dec->tags = list;
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
- GstCaps *caps;
- gint par_num, par_den;
- GstFlowReturn ret = GST_FLOW_OK;
- gboolean eret;
- GstEvent *event;
- guint32 bitstream_version;
-
- GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
- dec->info.fps_numerator, dec->info.fps_denominator,
- dec->info.aspect_numerator, dec->info.aspect_denominator);
-
- /* calculate par
- * the info.aspect_* values reflect PAR;
- * 0:0 is allowed and can be interpreted as 1:1, so correct for it */
- par_num = dec->info.aspect_numerator;
- par_den = dec->info.aspect_denominator;
- if (par_num == 0 && par_den == 0) {
- par_num = par_den = 1;
- }
- /* theora has:
- *
- * width/height : dimension of the encoded frame
- * frame_width/frame_height : dimension of the visible part
- * offset_x/offset_y : offset in encoded frame where visible part starts
- */
- GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
- dec->info.height, par_num, par_den);
- GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
- dec->info.frame_width, dec->info.frame_height,
- dec->info.offset_x, dec->info.offset_y);
- if (dec->info.pixelformat != OC_PF_420) {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("pixel formats other than 4:2:0 not yet supported"));
-
- return GST_FLOW_ERROR;
- }
-
- if (dec->crop) {
- /* add black borders to make width/height/offsets even. we need this because
- * we cannot express an offset to the peer plugin. */
- dec->width =
- GST_ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
- dec->height =
- GST_ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
- dec->offset_x = dec->info.offset_x & ~1;
- dec->offset_y = dec->info.offset_y & ~1;
- } else {
- /* no cropping, use the encoded dimensions */
- dec->width = dec->info.width;
- dec->height = dec->info.height;
- dec->offset_x = 0;
- dec->offset_y = 0;
- }
-
- dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);
-
- /* With libtheora-1.0beta1 the granulepos scheme was changed:
- * where earlier the granulepos refered to the index/beginning
- * of a frame, it now refers to the end, which matches the use
- * in vorbis/speex. We check the bitstream version from the header so
- * we know which way to interpret the incoming granuepos
- */
- bitstream_version = (dec->info.version_major << 16) |
- (dec->info.version_minor << 8) | dec->info.version_subminor;
- dec->is_old_bitstream = (bitstream_version <= 0x00030200);
-
- GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
- dec->width, dec->height, dec->offset_x, dec->offset_y);
-
- /* done */
- theora_decode_init (&dec->state, &dec->info);
-
- caps = gst_caps_new_simple ("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
- "framerate", GST_TYPE_FRACTION,
- dec->info.fps_numerator, dec->info.fps_denominator,
- "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
- "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
- gst_pad_set_caps (dec->srcpad, caps);
- gst_caps_unref (caps);
-
- dec->have_header = TRUE;
- if (!dec->sent_newsegment) {
- GST_DEBUG_OBJECT (dec, "Sending newsegment event");
-
- event = gst_event_new_new_segment_full (FALSE,
- dec->segment.rate, dec->segment.applied_rate,
- dec->segment.format, dec->segment.start, dec->segment.stop,
- dec->segment.time);
- eret = gst_pad_push_event (dec->srcpad, event);
- if (!eret)
- ret = GST_FLOW_ERROR;
- dec->sent_newsegment = TRUE;
- }
-
- if (dec->tags) {
- gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad,
- dec->tags);
- dec->tags = NULL;
- }
-
- return ret;
-}
-
-static GstFlowReturn
-theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
-{
- GstFlowReturn res;
-
- GST_DEBUG_OBJECT (dec, "parsing header packet");
-
- if (theora_decode_header (&dec->info, &dec->comment, packet))
- goto header_read_error;
-
- switch (packet->packet[0]) {
- case 0x81:
- res = theora_handle_comment_packet (dec, packet);
- break;
- case 0x82:
- res = theora_handle_type_packet (dec, packet);
- break;
- default:
- /* ignore */
- g_warning ("unknown theora header packet found");
- case 0x80:
- /* nothing special, this is the identification header */
- res = GST_FLOW_OK;
- break;
- }
- return res;
-
- /* ERRORS */
-header_read_error:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("couldn't read header packet"));
- return GST_FLOW_ERROR;
- }
-}
-
-/* returns TRUE if buffer is within segment, else FALSE.
- * if Buffer is on segment border, it's timestamp and duration will be clipped */
-static gboolean
-clip_buffer (GstTheoraDec * dec, GstBuffer * buf)
-{
- gboolean res = TRUE;
- GstClockTime in_ts, in_dur, stop;
- gint64 cstart, cstop;
-
- in_ts = GST_BUFFER_TIMESTAMP (buf);
- in_dur = GST_BUFFER_DURATION (buf);
-
- GST_LOG_OBJECT (dec,
- "timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT,
- GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur));
-
- /* can't clip without TIME segment */
- if (dec->segment.format != GST_FORMAT_TIME)
- goto beach;
-
- /* we need a start time */
- if (!GST_CLOCK_TIME_IS_VALID (in_ts))
- goto beach;
-
- /* generate valid stop, if duration unknown, we have unknown stop */
- stop =
- GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE;
-
- /* now clip */
- if (!(res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
- in_ts, stop, &cstart, &cstop)))
- goto beach;
-
- /* update timestamp and possibly duration if the clipped stop time is
- * valid */
- GST_BUFFER_TIMESTAMP (buf) = cstart;
- if (GST_CLOCK_TIME_IS_VALID (cstop))
- GST_BUFFER_DURATION (buf) = cstop - cstart;
-
-beach:
- GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
- return res;
-}
-
-/* FIXME, this needs to be moved to the demuxer */
-static GstFlowReturn
-theora_dec_push_forward (GstTheoraDec * dec, GstBuffer * buf)
-{
- GstFlowReturn result = GST_FLOW_OK;
- GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
-
- if (outtime == GST_CLOCK_TIME_NONE) {
- dec->queued = g_list_append (dec->queued, buf);
- GST_DEBUG_OBJECT (dec, "queued buffer");
- } else {
- if (dec->queued) {
- gint64 size;
- GList *walk;
-
- GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (outtime));
-
- size = g_list_length (dec->queued);
- for (walk = dec->queued; walk; walk = g_list_next (walk)) {
- GstBuffer *buffer = GST_BUFFER (walk->data);
- GstClockTime time;
-
- time = outtime - gst_util_uint64_scale_int (size * GST_SECOND,
- dec->info.fps_denominator, dec->info.fps_numerator);
-
- GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
- GST_BUFFER_TIMESTAMP (buffer) = time;
- /* Next timestamp - this one is duration */
- GST_BUFFER_DURATION (buffer) =
- (outtime - gst_util_uint64_scale_int ((size - 1) * GST_SECOND,
- dec->info.fps_denominator, dec->info.fps_numerator)) - time;
-
- if (dec->discont) {
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- dec->discont = FALSE;
- }
- /* ignore the result.. */
- if (clip_buffer (dec, buffer))
- gst_pad_push (dec->srcpad, buffer);
- else
- gst_buffer_unref (buffer);
- size--;
- }
- g_list_free (dec->queued);
- dec->queued = NULL;
- }
- if (dec->discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- dec->discont = FALSE;
- }
- if (clip_buffer (dec, buf))
- result = gst_pad_push (dec->srcpad, buf);
- else
- gst_buffer_unref (buf);
- }
- return result;
-}
-
-static GstFlowReturn
-theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf)
-{
- GstFlowReturn result = GST_FLOW_OK;
-
- dec->queued = g_list_prepend (dec->queued, buf);
-
- return result;
-}
-
-static GstFlowReturn
-theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
- GstClockTime outtime)
-{
- /* normal data packet */
- yuv_buffer yuv;
- GstBuffer *out;
- guint i;
- gboolean keyframe;
- gint out_size;
- gint stride_y, stride_uv;
- gint width, height;
- gint cwidth, cheight;
- GstFlowReturn result;
-
- if (G_UNLIKELY (!dec->have_header))
- goto not_initialized;
-
- /* the second most significant bit of the first data byte is cleared
- * for keyframes. We can only check it if it's not a zero-length packet. */
- keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0);
- if (G_UNLIKELY (keyframe)) {
- GST_DEBUG_OBJECT (dec, "we have a keyframe");
- dec->need_keyframe = FALSE;
- } else if (G_UNLIKELY (dec->need_keyframe)) {
- goto dropping;
- }
-
- GST_DEBUG_OBJECT (dec, "parsing data packet");
-
- /* this does the decoding */
- if (G_UNLIKELY (theora_decode_packetin (&dec->state, packet)))
- goto decode_error;
-
- if (outtime != -1) {
- gboolean need_skip;
- GstClockTime qostime;
-
- /* qos needs to be done on running time */
- qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
- outtime);
-
- GST_OBJECT_LOCK (dec);
- /* check for QoS, don't perform the last steps of getting and
- * pushing the buffers that are known to be late. */
- /* FIXME, we can also entirely skip decoding if the next valid buffer is
- * known to be after a keyframe (using the granule_shift) */
- need_skip = dec->earliest_time != -1 && qostime <= dec->earliest_time;
- GST_OBJECT_UNLOCK (dec);
-
- if (need_skip)
- goto dropping_qos;
- }
-
- /* this does postprocessing and set up the decoded frame
- * pointers in our yuv variable */
- if (G_UNLIKELY (theora_decode_YUVout (&dec->state, &yuv) < 0))
- goto no_yuv;
-
- if (G_UNLIKELY ((yuv.y_width != dec->info.width)
- || (yuv.y_height != dec->info.height)))
- goto wrong_dimensions;
-
- width = dec->width;
- height = dec->height;
- cwidth = width / 2;
- cheight = height / 2;
-
- /* should get the stride from the caps, for now we round up to the nearest
- * multiple of 4 because some element needs it. chroma needs special
- * treatment, see videotestsrc. */
- stride_y = GST_ROUND_UP_4 (width);
- stride_uv = GST_ROUND_UP_8 (width) / 2;
-
- out_size = stride_y * height + stride_uv * cheight * 2;
-
- /* now copy over the area contained in offset_x,offset_y,
- * frame_width, frame_height */
- result =
- gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
- out_size, GST_PAD_CAPS (dec->srcpad), &out);
- if (G_UNLIKELY (result != GST_FLOW_OK))
- goto no_buffer;
-
- /* copy the visible region to the destination. This is actually pretty
- * complicated and gstreamer doesn't support all the needed caps to do this
- * correctly. For example, when we have an odd offset, we should only combine
- * 1 row/column of luma samples with one chroma sample in colorspace conversion.
- * We compensate for this by adding a black border around the image when the
- * offset or size is odd (see above).
- */
- {
- guchar *dest_y, *src_y;
- guchar *dest_u, *src_u;
- guchar *dest_v, *src_v;
- gint offset;
-
- dest_y = GST_BUFFER_DATA (out);
- dest_u = dest_y + stride_y * height;
- dest_v = dest_u + stride_uv * cheight;
-
- src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride;
-
- for (i = 0; i < height; i++) {
- memcpy (dest_y, src_y, width);
-
- dest_y += stride_y;
- src_y += yuv.y_stride;
- }
-
- offset = dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
-
- src_u = yuv.u + offset;
- src_v = yuv.v + offset;
-
- for (i = 0; i < cheight; i++) {
- memcpy (dest_u, src_u, cwidth);
- memcpy (dest_v, src_v, cwidth);
-
- dest_u += stride_uv;
- src_u += yuv.uv_stride;
- dest_v += stride_uv;
- src_v += yuv.uv_stride;
- }
- }
-
- GST_BUFFER_OFFSET (out) = dec->frame_nr;
- if (dec->frame_nr != -1)
- dec->frame_nr++;
- GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
- if (dec->granulepos != -1) {
- gint64 cf = _theora_granule_frame (dec, dec->granulepos) + 1;
-
- GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (cf * GST_SECOND,
- dec->info.fps_denominator, dec->info.fps_numerator) - outtime;
- } else {
- GST_BUFFER_DURATION (out) =
- gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator,
- dec->info.fps_numerator);
- }
- GST_BUFFER_TIMESTAMP (out) = outtime;
-
- if (dec->segment.rate >= 0.0)
- result = theora_dec_push_forward (dec, out);
- else
- result = theora_dec_push_reverse (dec, out);
-
- return result;
-
- /* ERRORS */
-not_initialized:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("no header sent yet"));
- return GST_FLOW_ERROR;
- }
-dropping:
- {
- GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
- dec->discont = TRUE;
- return GST_FLOW_OK;
- }
-dropping_qos:
- {
- if (dec->frame_nr != -1)
- dec->frame_nr++;
- dec->discont = TRUE;
- GST_WARNING_OBJECT (dec, "dropping frame because of QoS");
- return GST_FLOW_OK;
- }
-decode_error:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("theora decoder did not decode data packet"));
- return GST_FLOW_ERROR;
- }
-no_yuv:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
- (NULL), ("couldn't read out YUV image"));
- return GST_FLOW_ERROR;
- }
-wrong_dimensions:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT,
- (NULL), ("dimensions of image do not match header"));
- return GST_FLOW_ERROR;
- }
-no_buffer:
- {
- GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
- gst_flow_get_name (result));
- return result;
- }
-}
-
-static GstFlowReturn
-theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf)
-{
- ogg_packet packet;
- GstFlowReturn result = GST_FLOW_OK;
-
- /* make ogg_packet out of the buffer */
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- packet.packetno = 0; /* we don't really care */
- packet.b_o_s = dec->have_header ? 0 : 1;
- /* EOS does not matter for the decoder */
- packet.e_o_s = 0;
-
- if (dec->have_header) {
- if (packet.granulepos != -1) {
- dec->granulepos = packet.granulepos;
- dec->last_timestamp = _theora_granule_start_time (dec, packet.granulepos);
- } else if (dec->last_timestamp != -1) {
- dec->last_timestamp = _theora_granule_start_time (dec, dec->granulepos);
- }
- if (dec->last_timestamp == -1 && GST_BUFFER_TIMESTAMP_IS_VALID (buf))
- dec->last_timestamp = GST_BUFFER_TIMESTAMP (buf);
- } else {
- dec->last_timestamp = -1;
- }
-
- GST_DEBUG_OBJECT (dec, "header=%02x packetno=%lld, granule pos=%"
- G_GINT64_FORMAT ", outtime=%" GST_TIME_FORMAT,
- packet.bytes ? packet.packet[0] : -1, packet.packetno, packet.granulepos,
- GST_TIME_ARGS (dec->last_timestamp));
-
- /* switch depending on packet type. A zero byte packet is always a data
- * packet; we don't dereference it in that case. */
- if (packet.bytes && packet.packet[0] & 0x80) {
- if (dec->have_header) {
- GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header");
- goto done;
- }
- result = theora_handle_header_packet (dec, &packet);
- } else {
- result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
- }
-
-done:
- /* interpolate granule pos */
- dec->granulepos = _inc_granulepos (dec, dec->granulepos);
-
- return result;
-}
-
-/* For reverse playback we use a technique that can be used for
- * any keyframe based video codec.
- *
- * Input:
- * Buffer decoding order: 7 8 9 4 5 6 1 2 3 EOS
- * Keyframe flag: K K
- * Discont flag: D D D
- *
- * - Each Discont marks a discont in the decoding order.
- * - The keyframes mark where we can start decoding.
- *
- * First we prepend incomming buffers to the gather queue, whenever we receive
- * a discont, we flush out the gather queue.
- *
- * The above data will be accumulated in the gather queue like this:
- *
- * gather queue: 9 8 7
- * D
- *
- * Whe buffer 4 is received (with a DISCONT), we flush the gather queue like
- * this:
- *
- * while (gather)
- * take head of queue and prepend to decode queue.
- * if we copied a keyframe, decode the decode queue.
- *
- * After we flushed the gather queue, we add 4 to the (now empty) gather queue.
- * We get the following situation:
- *
- * gather queue: 4
- * decode queue: 7 8 9
- *
- * After we received 5 (Keyframe) and 6:
- *
- * gather queue: 6 5 4
- * decode queue: 7 8 9
- *
- * When we receive 1 (DISCONT) which triggers a flush of the gather queue:
- *
- * Copy head of the gather queue (6) to decode queue:
- *
- * gather queue: 5 4
- * decode queue: 6 7 8 9
- *
- * Copy head of the gather queue (5) to decode queue. This is a keyframe so we
- * can start decoding.
- *
- * gather queue: 4
- * decode queue: 5 6 7 8 9
- *
- * Decode frames in decode queue, store raw decoded data in output queue, we
- * can take the head of the decode queue and prepend the decoded result in the
- * output queue:
- *
- * gather queue: 4
- * decode queue:
- * output queue: 9 8 7 6 5
- *
- * Now output all the frames in the output queue, picking a frame from the
- * head of the queue.
- *
- * Copy head of the gather queue (4) to decode queue, we flushed the gather
- * queue and can now store input buffer in the gather queue:
- *
- * gather queue: 1
- * decode queue: 4
- *
- * When we receive EOS, the queue looks like:
- *
- * gather queue: 3 2 1
- * decode queue: 4
- *
- * Fill decode queue, first keyframe we copy is 2:
- *
- * gather queue: 1
- * decode queue: 2 3 4
- *
- * Decoded output:
- *
- * gather queue: 1
- * decode queue:
- * output queue: 4 3 2
- *
- * Leftover buffer 1 cannot be decoded and must be discarded.
- */
-static GstFlowReturn
-theora_dec_flush_decode (GstTheoraDec * dec)
-{
- GstFlowReturn res = GST_FLOW_OK;
-
- while (dec->decode) {
- GstBuffer *buf = GST_BUFFER_CAST (dec->decode->data);
-
- GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
- buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
- /* decode buffer, prepend to output queue */
- res = theora_dec_decode_buffer (dec, buf);
-
- /* don't need it anymore now */
- gst_buffer_unref (buf);
-
- dec->decode = g_list_delete_link (dec->decode, dec->decode);
- }
- while (dec->queued) {
- GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data);
-
- /* iterate ouput queue an push downstream */
- res = gst_pad_push (dec->srcpad, buf);
-
- dec->queued = g_list_delete_link (dec->queued, dec->queued);
- }
-
- return res;
-}
-
-static GstFlowReturn
-theora_dec_chain_reverse (GstTheoraDec * dec, gboolean discont, GstBuffer * buf)
-{
- GstFlowReturn res = GST_FLOW_OK;
-
- /* if we have a discont, move buffers to the decode list */
- if (G_UNLIKELY (discont)) {
- GST_DEBUG_OBJECT (dec, "received discont,gathering buffers");
- while (dec->gather) {
- GstBuffer *gbuf;
- guint8 *data;
-
- gbuf = GST_BUFFER_CAST (dec->gather->data);
- /* remove from the gather list */
- dec->gather = g_list_delete_link (dec->gather, dec->gather);
- /* copy to decode queue */
- dec->decode = g_list_prepend (dec->decode, gbuf);
-
- /* if we copied a keyframe, flush and decode the decode queue */
- data = GST_BUFFER_DATA (gbuf);
- if ((data[0] & 0x40) == 0) {
- GST_DEBUG_OBJECT (dec, "copied keyframe");
- res = theora_dec_flush_decode (dec);
- }
- }
- }
-
- /* add buffer to gather queue */
- GST_DEBUG_OBJECT (dec, "gathering buffer %p, size %u", buf,
- GST_BUFFER_SIZE (buf));
- dec->gather = g_list_prepend (dec->gather, buf);
-
- return res;
-}
-
-static GstFlowReturn
-theora_dec_chain_forward (GstTheoraDec * dec, gboolean discont,
- GstBuffer * buffer)
-{
- GstFlowReturn result;
-
- result = theora_dec_decode_buffer (dec, buffer);
-
- gst_buffer_unref (buffer);
-
- return result;
-}
-
-static GstFlowReturn
-theora_dec_chain (GstPad * pad, GstBuffer * buf)
-{
- GstTheoraDec *dec;
- GstFlowReturn res;
- gboolean discont;
-
- dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
-
- /* peel of DISCONT flag */
- discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT);
-
- /* resync on DISCONT */
- if (G_UNLIKELY (discont)) {
- GST_DEBUG_OBJECT (dec, "received DISCONT buffer");
- dec->need_keyframe = TRUE;
- dec->last_timestamp = -1;
- dec->granulepos = -1;
- dec->discont = TRUE;
- }
-
- if (dec->segment.rate > 0.0)
- res = theora_dec_chain_forward (dec, discont, buf);
- else
- res = theora_dec_chain_reverse (dec, discont, buf);
-
- gst_object_unref (dec);
-
- return res;
-}
-
-static GstStateChangeReturn
-theora_dec_change_state (GstElement * element, GstStateChange transition)
-{
- GstTheoraDec *dec = GST_THEORA_DEC (element);
- GstStateChangeReturn ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- theora_info_init (&dec->info);
- theora_comment_init (&dec->comment);
- GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED");
- dec->have_header = FALSE;
- gst_theora_dec_reset (dec);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- theora_clear (&dec->state);
- theora_comment_clear (&dec->comment);
- theora_info_clear (&dec->info);
- gst_theora_dec_reset (dec);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static void
-theora_dec_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTheoraDec *dec = GST_THEORA_DEC (object);
-
- switch (prop_id) {
- case ARG_CROP:
- dec->crop = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-theora_dec_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTheoraDec *dec = GST_THEORA_DEC (object);
-
- switch (prop_id) {
- case ARG_CROP:
- g_value_set_boolean (value, dec->crop);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
--- a/gst_plugins_base/ext/theora/theoraenc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1104 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Wim Taymans <wim@fluendo.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.
- */
-
-/**
- * SECTION:element-theoraenc
- * @see_also: theoradec, oggmux
- *
- * <refsect2>
- * <para>
- * This element encodes raw video into a Theora stream.
- * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
- * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>, based on the VP3 codec.
- * </para>
- * <para>
- * The theora codec internally only supports encoding of images that are a
- * multiple of 16 pixels in both X and Y direction. It is however perfectly
- * possible to encode images with other dimensions because an arbitrary
- * rectangular cropping region can be set up. This element will automatically
- * set up a correct cropping region if the dimensions are not multiples of 16
- * pixels. The "border" and "center" properties control how this cropping
- * region will be set up.
- * </para>
- * <para>
- * To control the quality of the encoding, the "bitrate" and "quality"
- * properties can be used. These two properties are mutualy exclusive. Setting
- * the bitrate property will produce a constant bitrate (CBR) stream while
- * setting the quality property will produce a variable bitrate (VBR) stream.
- * </para>
- * <title>Example pipeline</title>
- * <programlisting>
- * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg
- * </programlisting>
- * This example pipeline will encode a test video source to theora muxed in an
- * ogg container. Refer to the theoradec documentation to decode the create
- * stream.
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gsttheoraenc.h"
-
-#include <string.h>
-#include <stdlib.h> /* free */
-
-#include <gst/tag/tag.h>
-
-#define GST_CAT_DEFAULT theoraenc_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-/* With libtheora-1.0beta1 the granulepos scheme was changed:
- * where earlier the granulepos refered to the index/beginning
- * of a frame, it now refers to the end, which matches the use
- * in vorbis/speex. There don't seem to be defines for the
- * theora version we're compiling against, so we'll just use
- * a run-time check for now. See theora_enc_get_ogg_packet_end_time().
- */
-static gboolean use_old_granulepos;
-
-#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
-static GType
-gst_border_mode_get_type (void)
-{
- static GType border_mode_type = 0;
- static const GEnumValue border_mode[] = {
- {BORDER_NONE, "No Border", "none"},
- {BORDER_BLACK, "Black Border", "black"},
- {BORDER_MIRROR, "Mirror image in borders", "mirror"},
- {0, NULL, NULL},
- };
-
- if (!border_mode_type) {
- border_mode_type =
- g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
- }
- return border_mode_type;
-}
-
-/* taken from theora/lib/toplevel.c */
-static int
-_ilog (unsigned int v)
-{
- int ret = 0;
-
- while (v) {
- ret++;
- v >>= 1;
- }
- return (ret);
-}
-
-#define THEORA_DEF_CENTER TRUE
-#define THEORA_DEF_BORDER BORDER_BLACK
-#define THEORA_DEF_BITRATE 0
-#define THEORA_DEF_QUALITY 16
-#define THEORA_DEF_QUICK TRUE
-#define THEORA_DEF_KEYFRAME_AUTO TRUE
-#define THEORA_DEF_KEYFRAME_FREQ 64
-#define THEORA_DEF_KEYFRAME_FREQ_FORCE 64
-#define THEORA_DEF_KEYFRAME_THRESHOLD 80
-#define THEORA_DEF_KEYFRAME_MINDISTANCE 8
-#define THEORA_DEF_NOISE_SENSITIVITY 1
-#define THEORA_DEF_SHARPNESS 0
-enum
-{
- ARG_0,
- ARG_CENTER,
- ARG_BORDER,
- ARG_BITRATE,
- ARG_QUALITY,
- ARG_QUICK,
- ARG_KEYFRAME_AUTO,
- ARG_KEYFRAME_FREQ,
- ARG_KEYFRAME_FREQ_FORCE,
- ARG_KEYFRAME_THRESHOLD,
- ARG_KEYFRAME_MINDISTANCE,
- ARG_NOISE_SENSITIVITY,
- ARG_SHARPNESS,
- /* FILL ME */
-};
-
-/* this function does a straight granulepos -> timestamp conversion */
-static GstClockTime
-granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos)
-{
- guint64 iframe, pframe;
- int shift = theoraenc->granule_shift;
-
- if (granulepos < 0)
- return GST_CLOCK_TIME_NONE;
-
- iframe = granulepos >> shift;
- pframe = granulepos - (iframe << shift);
-
- /* num and den are 32 bit, so we can safely multiply with GST_SECOND */
- return gst_util_uint64_scale ((guint64) (iframe + pframe),
- GST_SECOND * theoraenc->info.fps_denominator,
- theoraenc->info.fps_numerator);
-}
-
-static const GstElementDetails theora_enc_details =
-GST_ELEMENT_DETAILS ("Theora video encoder",
- "Codec/Encoder/Video",
- "encode raw YUV video to a theora stream",
- "Wim Taymans <wim@fluendo.com>");
-
-static GstStaticPadTemplate theora_enc_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-yuv, "
- "format = (fourcc) I420, "
- "framerate = (fraction) [0/1, MAX], "
- "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
- );
-
-static GstStaticPadTemplate theora_enc_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-theora")
- );
-
-GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstElement, GST_TYPE_ELEMENT);
-
-static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_enc_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps);
-static void theora_enc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void theora_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void theora_enc_finalize (GObject * object);
-
-static void
-gst_theora_enc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_enc_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_enc_sink_factory));
- gst_element_class_set_details (element_class, &theora_enc_details);
-}
-
-static void
-gst_theora_enc_class_init (GstTheoraEncClass * klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->set_property = theora_enc_set_property;
- gobject_class->get_property = theora_enc_get_property;
- gobject_class->finalize = theora_enc_finalize;
-
- g_object_class_install_property (gobject_class, ARG_CENTER,
- g_param_spec_boolean ("center", "Center",
- "Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_BORDER,
- g_param_spec_enum ("border", "Border",
- "Border color to add when sizes not multiple of 16",
- GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
- (GParamFlags) G_PARAM_READWRITE));
- /* general encoding stream options */
- g_object_class_install_property (gobject_class, ARG_BITRATE,
- g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
- 0, 2000, THEORA_DEF_BITRATE, (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_QUALITY,
- g_param_spec_int ("quality", "Quality", "Video quality",
- 0, 63, THEORA_DEF_QUALITY, (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_QUICK,
- g_param_spec_boolean ("quick", "Quick", "Quick encoding",
- THEORA_DEF_QUICK, (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME_AUTO,
- g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
- "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ,
- g_param_spec_int ("keyframe-freq", "Keyframe frequency",
- "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME_FREQ_FORCE,
- g_param_spec_int ("keyframe-force", "Keyframe force",
- "Force keyframe every N frames", 1, 32768,
- THEORA_DEF_KEYFRAME_FREQ_FORCE, (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME_THRESHOLD,
- g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
- "Keyframe threshold", 0, 32768, THEORA_DEF_KEYFRAME_THRESHOLD,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME_MINDISTANCE,
- g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
- "Keyframe mindistance", 1, 32768, THEORA_DEF_KEYFRAME_MINDISTANCE,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_NOISE_SENSITIVITY,
- g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
- "Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
- (GParamFlags) G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_SHARPNESS,
- g_param_spec_int ("sharpness", "Sharpness",
- "Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
- (GParamFlags) G_PARAM_READWRITE));
-
- gstelement_class->change_state = theora_enc_change_state;
- GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
-
- use_old_granulepos = (theora_version_number () <= 0x00030200);
-}
-
-static void
-gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
-{
- enc->sinkpad =
- gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink");
- gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain);
- gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event);
- gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps);
- gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad);
-
- enc->srcpad =
- gst_pad_new_from_static_template (&theora_enc_src_factory, "src");
- gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
-
- enc->center = THEORA_DEF_CENTER;
- enc->border = THEORA_DEF_BORDER;
-
- enc->video_bitrate = THEORA_DEF_BITRATE;
- enc->video_quality = THEORA_DEF_QUALITY;
- enc->quick = THEORA_DEF_QUICK;
- enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
- enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ;
- enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE;
- enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
- enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
- enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
- enc->sharpness = THEORA_DEF_SHARPNESS;
-
- enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
- GST_DEBUG_OBJECT (enc,
- "keyframe_frequency_force is %d, granule shift is %d",
- enc->info.keyframe_frequency_force, enc->granule_shift);
- enc->expected_ts = GST_CLOCK_TIME_NONE;
-}
-
-static void
-theora_enc_finalize (GObject * object)
-{
- GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
- GST_DEBUG_OBJECT (enc, "Finalizing");
- theora_clear (&enc->state);
- theora_comment_clear (&enc->comment);
- theora_info_clear (&enc->info);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-theora_enc_reset (GstTheoraEnc * enc)
-{
- theora_clear (&enc->state);
- theora_encode_init (&enc->state, &enc->info);
-}
-
-static void
-theora_enc_clear (GstTheoraEnc * enc)
-{
- enc->packetno = 0;
- enc->bytes_out = 0;
- enc->granulepos_offset = 0;
- enc->timestamp_offset = 0;
-
- enc->next_ts = GST_CLOCK_TIME_NONE;
- enc->next_discont = FALSE;
- enc->expected_ts = GST_CLOCK_TIME_NONE;
-}
-
-static gboolean
-theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstStructure *structure = gst_caps_get_structure (caps, 0);
- GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
- const GValue *par;
- gint fps_n, fps_d;
-
- gst_structure_get_int (structure, "width", &enc->width);
- gst_structure_get_int (structure, "height", &enc->height);
- gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
- par = gst_structure_get_value (structure, "pixel-aspect-ratio");
-
- theora_info_clear (&enc->info);
- theora_info_init (&enc->info);
- /* Theora has a divisible-by-sixteen restriction for the encoded video size but
- * we can define a visible area using the frame_width/frame_height */
- enc->info_width = enc->info.width = (enc->width + 15) & ~15;
- enc->info_height = enc->info.height = (enc->height + 15) & ~15;
- enc->info.frame_width = enc->width;
- enc->info.frame_height = enc->height;
-
- /* center image if needed */
- if (enc->center) {
- /* make sure offset is even, for easier decoding */
- enc->offset_x = GST_ROUND_UP_2 ((enc->info_width - enc->width) / 2);
- enc->offset_y = GST_ROUND_UP_2 ((enc->info_height - enc->height) / 2);
- } else {
- enc->offset_x = 0;
- enc->offset_y = 0;
- }
- enc->info.offset_x = enc->offset_x;
- enc->info.offset_y = enc->offset_y;
-
- enc->info.fps_numerator = enc->fps_n = fps_n;
- enc->info.fps_denominator = enc->fps_d = fps_d;
- if (par) {
- enc->info.aspect_numerator = gst_value_get_fraction_numerator (par);
- enc->info.aspect_denominator = gst_value_get_fraction_denominator (par);
- } else {
- /* setting them to 0 indicates that the decoder can chose a good aspect
- * ratio, defaulting to 1/1 */
- enc->info.aspect_numerator = 0;
- enc->info.aspect_denominator = 0;
- }
-
- enc->info.colorspace = OC_CS_UNSPECIFIED;
- enc->info.target_bitrate = enc->video_bitrate;
- enc->info.quality = enc->video_quality;
-
- enc->info.dropframes_p = 0;
- enc->info.quick_p = (enc->quick ? 1 : 0);
- enc->info.keyframe_auto_p = (enc->keyframe_auto ? 1 : 0);
- enc->info.keyframe_frequency = enc->keyframe_freq;
- enc->info.keyframe_frequency_force = enc->keyframe_force;
- enc->info.keyframe_data_target_bitrate = enc->video_bitrate * 1.5;
- enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
- enc->info.keyframe_mindistance = enc->keyframe_mindistance;
- enc->info.noise_sensitivity = enc->noise_sensitivity;
- enc->info.sharpness = enc->sharpness;
-
- /* as done in theora */
- enc->granule_shift = _ilog (enc->info.keyframe_frequency_force - 1);
- GST_DEBUG_OBJECT (enc,
- "keyframe_frequency_force is %d, granule shift is %d",
- enc->info.keyframe_frequency_force, enc->granule_shift);
-
- theora_enc_reset (enc);
- enc->initialised = TRUE;
-
- gst_object_unref (enc);
-
- return TRUE;
-}
-
-static guint64
-granulepos_add (guint64 granulepos, guint64 addend, gint shift)
-{
- guint64 iframe, pframe;
-
- iframe = granulepos >> shift;
- pframe = granulepos - (iframe << shift);
- iframe += addend;
-
- return (iframe << shift) + pframe;
-}
-
-/* prepare a buffer for transmission by passing data through libtheora */
-static GstFlowReturn
-theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
- GstClockTime timestamp, GstClockTime duration, GstBuffer ** buffer)
-{
- GstBuffer *buf;
- GstFlowReturn ret = GST_FLOW_OK;
-
- buf = gst_buffer_new_and_alloc (packet->bytes);
- if (!buf) {
- GST_WARNING_OBJECT (enc, "Could not allocate buffer");
- ret = GST_FLOW_ERROR;
- goto done;
- }
-
- memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad));
- /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
- * time representation */
- GST_BUFFER_OFFSET_END (buf) =
- granulepos_add (packet->granulepos, enc->granulepos_offset,
- enc->granule_shift);
- GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc,
- GST_BUFFER_OFFSET_END (buf));
-
- GST_BUFFER_TIMESTAMP (buf) = timestamp + enc->timestamp_offset;
- GST_BUFFER_DURATION (buf) = duration;
-
- if (enc->next_discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- enc->next_discont = FALSE;
- }
-
- /* the second most significant bit of the first data byte is cleared
- * for keyframes */
- if ((packet->packet[0] & 0x40) == 0) {
- GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
- } else {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
- }
- enc->packetno++;
-
-done:
- *buffer = buf;
- return ret;
-}
-
-/* push out the buffer and do internal bookkeeping */
-static GstFlowReturn
-theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
-{
- GstFlowReturn ret;
-
- enc->bytes_out += GST_BUFFER_SIZE (buffer);
-
- ret = gst_pad_push (enc->srcpad, buffer);
-
- return ret;
-}
-
-static GstFlowReturn
-theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
- GstClockTime timestamp, GstClockTime duration)
-{
- GstBuffer *buf;
- GstFlowReturn ret;
-
- ret = theora_buffer_from_packet (enc, packet, timestamp, duration, &buf);
- if (ret == GST_FLOW_OK)
- ret = theora_push_buffer (enc, buf);
-
- return ret;
-}
-
-static GstCaps *
-theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
- GstBuffer * buf2, GstBuffer * buf3)
-{
- GstStructure *structure;
- GValue array = { 0 };
- GValue value = { 0 };
-
- caps = gst_caps_make_writable (caps);
- structure = gst_caps_get_structure (caps, 0);
-
- /* mark buffers */
- GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
- /* Copy buffers, because we can't use the originals -
- * it creates a circular refcount with the caps<->buffers */
- buf1 = gst_buffer_copy (buf1);
- buf2 = gst_buffer_copy (buf2);
- buf3 = gst_buffer_copy (buf3);
-
- /* put copies of the buffers in a fixed list */
- g_value_init (&array, GST_TYPE_ARRAY);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf1);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf2);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf3);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
-
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&array);
-
- /* Unref our copies */
- gst_buffer_unref (buf1);
- gst_buffer_unref (buf2);
- gst_buffer_unref (buf3);
-
- return caps;
-}
-
-static GstClockTime
-theora_enc_get_ogg_packet_end_time (GstTheoraEnc * enc, ogg_packet * op)
-{
- ogg_int64_t end_granule;
-
- /* FIXME: remove this hack once we depend on libtheora >= 1.0beta1 */
- if (G_UNLIKELY (use_old_granulepos)) {
- /* This is where we hack around theora's broken idea of what granulepos
- * is -- normally we wouldn't need to add the 1, because granulepos
- * should be the presentation time of the last sample in the packet, but
- * theora starts with 0 instead of 1... (update: this only applies to old
- * bitstream/theora versions, this is fixed with bitstream version 3.2.1) */
- end_granule = granulepos_add (op->granulepos, 1, enc->granule_shift);
- } else {
- end_granule = op->granulepos;
- }
- return theora_granule_time (&enc->state, end_granule) * GST_SECOND;
-}
-
-static gboolean
-theora_enc_sink_event (GstPad * pad, GstEvent * event)
-{
- GstTheoraEnc *enc;
- ogg_packet op;
- gboolean res;
-
- enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- if (enc->initialised) {
- /* push last packet with eos flag */
- while (theora_encode_packetout (&enc->state, 1, &op)) {
- GstClockTime next_time =
- theora_enc_get_ogg_packet_end_time (enc, &op);
-
- theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
- enc->next_ts = next_time;
- }
- }
- res = gst_pad_push_event (enc->srcpad, event);
- break;
- case GST_EVENT_CUSTOM_DOWNSTREAM:
- {
- const GstStructure *s;
-
- s = gst_event_get_structure (event);
-
- if (gst_structure_has_name (s, "GstForceKeyUnit")) {
- GstClockTime next_ts;
-
- /* make sure timestamps increment after resetting the decoder */
- next_ts = enc->next_ts + enc->timestamp_offset;
-
- theora_enc_reset (enc);
- enc->granulepos_offset =
- gst_util_uint64_scale (next_ts, enc->fps_n,
- GST_SECOND * enc->fps_d);
- enc->timestamp_offset = next_ts;
- enc->next_ts = 0;
- }
- res = gst_pad_push_event (enc->srcpad, event);
- break;
- }
- default:
- res = gst_pad_push_event (enc->srcpad, event);
- break;
- }
- return res;
-}
-
-static gboolean
-theora_enc_is_discontinuous (GstTheoraEnc * enc, GstBuffer * buffer)
-{
- GstClockTime ts = GST_BUFFER_TIMESTAMP (buffer);
- GstClockTimeDiff max_diff;
- gboolean ret = FALSE;
-
- /* Allow 3/4 a frame off */
- max_diff = (enc->info.fps_denominator * GST_SECOND * 3) /
- (enc->info.fps_numerator * 4);
-
- if (ts != GST_CLOCK_TIME_NONE && enc->expected_ts != GST_CLOCK_TIME_NONE) {
- if ((GstClockTimeDiff) (ts - enc->expected_ts) > max_diff) {
- GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT
- " exceeds expected value %" GST_TIME_FORMAT
- " by too much, marking discontinuity",
- GST_TIME_ARGS (ts), GST_TIME_ARGS (enc->expected_ts));
- ret = TRUE;
- }
- }
-
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer)))
- enc->expected_ts = ts + GST_BUFFER_DURATION (buffer);
- else
- enc->expected_ts = GST_CLOCK_TIME_NONE;
-
- return ret;
-}
-
-static GstFlowReturn
-theora_enc_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstTheoraEnc *enc;
- ogg_packet op;
- GstClockTime in_time;
- GstFlowReturn ret;
-
- enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
-
- in_time = GST_BUFFER_TIMESTAMP (buffer);
-
- if (enc->packetno == 0) {
- /* no packets written yet, setup headers */
- GstCaps *caps;
- GstBuffer *buf1, *buf2, *buf3;
-
- enc->granulepos_offset = 0;
- enc->timestamp_offset = 0;
-
- GST_DEBUG_OBJECT (enc, "output headers");
- /* Theora streams begin with three headers; the initial header (with
- most of the codec setup parameters) which is mandated by the Ogg
- bitstream spec. The second header holds any comment fields. The
- third header holds the bitstream codebook. We merely need to
- make the headers, then pass them to libtheora one at a time;
- libtheora handles the additional Ogg bitstream constraints */
-
- /* first packet will get its own page automatically */
- if (theora_encode_header (&enc->state, &op) != 0)
- goto encoder_disabled;
-
- ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
- GST_CLOCK_TIME_NONE, &buf1);
- if (ret != GST_FLOW_OK) {
- goto header_buffer_alloc;
- }
-
- /* create the remaining theora headers */
- theora_comment_clear (&enc->comment);
- theora_comment_init (&enc->comment);
-
- if (theora_encode_comment (&enc->comment, &op) != 0)
- goto encoder_disabled;
-
- ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
- GST_CLOCK_TIME_NONE, &buf2);
- /* Theora expects us to put this packet buffer into an ogg page,
- * in which case it becomes the ogg library's responsibility to
- * free it. Since we're copying and outputting a gst_buffer,
- * we need to free it ourselves. */
- if (op.packet)
- free (op.packet);
-
- if (ret != GST_FLOW_OK) {
- gst_buffer_unref (buf1);
- goto header_buffer_alloc;
- }
-
- if (theora_encode_tables (&enc->state, &op) != 0)
- goto encoder_disabled;
-
- ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE,
- GST_CLOCK_TIME_NONE, &buf3);
- if (ret != GST_FLOW_OK) {
- gst_buffer_unref (buf1);
- gst_buffer_unref (buf2);
- goto header_buffer_alloc;
- }
-
- /* mark buffers and put on caps */
- caps = gst_pad_get_caps (enc->srcpad);
- caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
- GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
- gst_pad_set_caps (enc->srcpad, caps);
-
- gst_buffer_set_caps (buf1, caps);
- gst_buffer_set_caps (buf2, caps);
- gst_buffer_set_caps (buf3, caps);
-
- gst_caps_unref (caps);
-
- /* push out the header buffers */
- if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) {
- gst_buffer_unref (buf2);
- gst_buffer_unref (buf3);
- goto header_push;
- }
- if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK) {
- gst_buffer_unref (buf3);
- goto header_push;
- }
- if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK) {
- goto header_push;
- }
-
- enc->granulepos_offset =
- gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
- enc->timestamp_offset = in_time;
- enc->next_ts = 0;
- }
-
- {
- yuv_buffer yuv;
- gint res;
- gint y_size;
- guint8 *pixels;
-
- yuv.y_width = enc->info_width;
- yuv.y_height = enc->info_height;
- yuv.y_stride = enc->info_width;
-
- yuv.uv_width = enc->info_width / 2;
- yuv.uv_height = enc->info_height / 2;
- yuv.uv_stride = yuv.uv_width;
-
- y_size = enc->info_width * enc->info_height;
-
- if (enc->width == enc->info_width && enc->height == enc->info_height) {
- GST_LOG_OBJECT (enc, "no cropping/conversion needed");
- /* easy case, no cropping/conversion needed */
- pixels = GST_BUFFER_DATA (buffer);
-
- yuv.y = pixels;
- yuv.u = yuv.y + y_size;
- yuv.v = yuv.u + y_size / 4;
- } else {
- GstBuffer *newbuf;
- gint i;
- guchar *dest_y, *src_y;
- guchar *dest_u, *src_u;
- guchar *dest_v, *src_v;
- gint src_y_stride, src_uv_stride;
- gint dst_y_stride, dst_uv_stride;
- gint width, height;
- gint cwidth, cheight;
- gint offset_x, right_x, right_border;
-
- GST_LOG_OBJECT (enc, "cropping/conversion needed for strides");
- /* source width/height */
- width = enc->width;
- height = enc->height;
- /* soucre chroma width/height */
- cwidth = width / 2;
- cheight = height / 2;
-
- /* source strides as defined in videotestsrc */
- src_y_stride = GST_ROUND_UP_4 (width);
- src_uv_stride = GST_ROUND_UP_8 (width) / 2;
-
- /* destination strides from the real picture width */
- dst_y_stride = enc->info_width;
- dst_uv_stride = enc->info_width / 2;
-
- newbuf = gst_buffer_new_and_alloc (y_size * 3 / 2);
- if (!newbuf) {
- ret = GST_FLOW_ERROR;
- goto no_buffer;
- }
- GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET_NONE;
- gst_buffer_set_caps (newbuf, GST_PAD_CAPS (enc->srcpad));
-
- dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
- dest_u = yuv.u = yuv.y + y_size;
- dest_v = yuv.v = yuv.u + y_size / 4;
-
- src_y = GST_BUFFER_DATA (buffer);
- src_u = src_y + src_y_stride * GST_ROUND_UP_2 (height);
- src_v = src_u + src_uv_stride * GST_ROUND_UP_2 (height) / 2;
-
- if (enc->border != BORDER_NONE) {
- /* fill top border */
- for (i = 0; i < enc->offset_y; i++) {
- memset (dest_y, 0, dst_y_stride);
- dest_y += dst_y_stride;
- }
- } else {
- dest_y += dst_y_stride * enc->offset_y;
- }
-
- offset_x = enc->offset_x;
- right_x = width + enc->offset_x;
- right_border = dst_y_stride - right_x;
-
- /* copy Y plane */
- for (i = 0; i < height; i++) {
- memcpy (dest_y + offset_x, src_y, width);
- if (enc->border != BORDER_NONE) {
- memset (dest_y, 0, offset_x);
- memset (dest_y + right_x, 0, right_border);
- }
-
- dest_y += dst_y_stride;
- src_y += src_y_stride;
- }
-
- if (enc->border != BORDER_NONE) {
- /* fill bottom border */
- for (i = height + enc->offset_y; i < enc->info.height; i++) {
- memset (dest_y, 0, dst_y_stride);
- dest_y += dst_y_stride;
- }
-
- /* fill top border chroma */
- for (i = 0; i < enc->offset_y / 2; i++) {
- memset (dest_u, 128, dst_uv_stride);
- memset (dest_v, 128, dst_uv_stride);
- dest_u += dst_uv_stride;
- dest_v += dst_uv_stride;
- }
- } else {
- dest_u += dst_uv_stride * enc->offset_y / 2;
- dest_v += dst_uv_stride * enc->offset_y / 2;
- }
-
- offset_x = enc->offset_x / 2;
- right_x = cwidth + offset_x;
- right_border = dst_uv_stride - right_x;
-
- /* copy UV planes */
- for (i = 0; i < cheight; i++) {
- memcpy (dest_v + offset_x, src_v, cwidth);
- memcpy (dest_u + offset_x, src_u, cwidth);
-
- if (enc->border != BORDER_NONE) {
- memset (dest_u, 128, offset_x);
- memset (dest_u + right_x, 128, right_border);
- memset (dest_v, 128, offset_x);
- memset (dest_v + right_x, 128, right_border);
- }
-
- dest_u += dst_uv_stride;
- dest_v += dst_uv_stride;
- src_u += src_uv_stride;
- src_v += src_uv_stride;
- }
-
- if (enc->border != BORDER_NONE) {
- /* fill bottom border */
- for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
- memset (dest_u, 128, dst_uv_stride);
- memset (dest_v, 128, dst_uv_stride);
- dest_u += dst_uv_stride;
- dest_v += dst_uv_stride;
- }
- }
-
- gst_buffer_unref (buffer);
- buffer = newbuf;
- }
-
- if (theora_enc_is_discontinuous (enc, buffer)) {
- theora_enc_reset (enc);
- enc->granulepos_offset =
- gst_util_uint64_scale (in_time, enc->fps_n, GST_SECOND * enc->fps_d);
- enc->timestamp_offset = in_time;
- enc->next_ts = 0;
- enc->next_discont = TRUE;
- }
-
- res = theora_encode_YUVin (&enc->state, &yuv);
-
- ret = GST_FLOW_OK;
- while (theora_encode_packetout (&enc->state, 0, &op)) {
- GstClockTime next_time = theora_enc_get_ogg_packet_end_time (enc, &op);
-
- ret =
- theora_push_packet (enc, &op, enc->next_ts, next_time - enc->next_ts);
- enc->next_ts = next_time;
- if (ret != GST_FLOW_OK)
- goto data_push;
- }
- gst_buffer_unref (buffer);
- }
-
- return ret;
-
- /* ERRORS */
-header_buffer_alloc:
- {
- gst_buffer_unref (buffer);
- return ret;
- }
-header_push:
- {
- gst_buffer_unref (buffer);
- return ret;
- }
-no_buffer:
- {
- return ret;
- }
-data_push:
- {
- gst_buffer_unref (buffer);
- return ret;
- }
-encoder_disabled:
- {
- GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
- ("libtheora has been compiled with the encoder disabled"));
- gst_buffer_unref (buffer);
- return GST_FLOW_ERROR;
- }
-}
-
-static GstStateChangeReturn
-theora_enc_change_state (GstElement * element, GstStateChange transition)
-{
- GstTheoraEnc *enc;
- GstStateChangeReturn ret;
-
- enc = GST_THEORA_ENC (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state");
- theora_info_init (&enc->info);
- theora_comment_init (&enc->comment);
- enc->packetno = 0;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state");
- theora_clear (&enc->state);
- theora_comment_clear (&enc->comment);
- theora_info_clear (&enc->info);
-
- theora_enc_clear (enc);
- enc->initialised = FALSE;
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static void
-theora_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
- switch (prop_id) {
- case ARG_CENTER:
- enc->center = g_value_get_boolean (value);
- break;
- case ARG_BORDER:
- enc->border = g_value_get_enum (value);
- break;
- case ARG_BITRATE:
- enc->video_bitrate = g_value_get_int (value) * 1000;
- enc->video_quality = 0;
- break;
- case ARG_QUALITY:
- enc->video_quality = g_value_get_int (value);
- enc->video_bitrate = 0;
- break;
- case ARG_QUICK:
- enc->quick = g_value_get_boolean (value);
- break;
- case ARG_KEYFRAME_AUTO:
- enc->keyframe_auto = g_value_get_boolean (value);
- break;
- case ARG_KEYFRAME_FREQ:
- enc->keyframe_freq = g_value_get_int (value);
- break;
- case ARG_KEYFRAME_FREQ_FORCE:
- enc->keyframe_force = g_value_get_int (value);
- break;
- case ARG_KEYFRAME_THRESHOLD:
- enc->keyframe_threshold = g_value_get_int (value);
- break;
- case ARG_KEYFRAME_MINDISTANCE:
- enc->keyframe_mindistance = g_value_get_int (value);
- break;
- case ARG_NOISE_SENSITIVITY:
- enc->noise_sensitivity = g_value_get_int (value);
- break;
- case ARG_SHARPNESS:
- enc->sharpness = g_value_get_int (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-theora_enc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTheoraEnc *enc = GST_THEORA_ENC (object);
-
- switch (prop_id) {
- case ARG_CENTER:
- g_value_set_boolean (value, enc->center);
- break;
- case ARG_BORDER:
- g_value_set_enum (value, enc->border);
- break;
- case ARG_BITRATE:
- g_value_set_int (value, enc->video_bitrate / 1000);
- break;
- case ARG_QUALITY:
- g_value_set_int (value, enc->video_quality);
- break;
- case ARG_QUICK:
- g_value_set_boolean (value, enc->quick);
- break;
- case ARG_KEYFRAME_AUTO:
- g_value_set_boolean (value, enc->keyframe_auto);
- break;
- case ARG_KEYFRAME_FREQ:
- g_value_set_int (value, enc->keyframe_freq);
- break;
- case ARG_KEYFRAME_FREQ_FORCE:
- g_value_set_int (value, enc->keyframe_force);
- break;
- case ARG_KEYFRAME_THRESHOLD:
- g_value_set_int (value, enc->keyframe_threshold);
- break;
- case ARG_KEYFRAME_MINDISTANCE:
- g_value_set_int (value, enc->keyframe_mindistance);
- break;
- case ARG_NOISE_SENSITIVITY:
- g_value_set_int (value, enc->noise_sensitivity);
- break;
- case ARG_SHARPNESS:
- g_value_set_int (value, enc->sharpness);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
--- a/gst_plugins_base/ext/theora/theoraparse.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,917 +0,0 @@
-/* GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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.
- */
-
-/**
- * SECTION:element-theoraparse
- * @short_description: parses theora streams
- * @see_also: theoradec, oggdemux, vorbisparse
- *
- * <refsect2>
- * <para>
- * The theoraparse element will parse the header packets of the Theora
- * stream and put them as the streamheader in the caps. This is used in the
- * multifdsink case where you want to stream live theora streams to multiple
- * clients, each client has to receive the streamheaders first before they can
- * consume the theora packets.
- * </para>
- * <para>
- * This element also makes sure that the buffers that it pushes out are properly
- * timestamped and that their offset and offset_end are set. The buffers that
- * vorbisparse outputs have all of the metadata that oggmux expects to receive,
- * which allows you to (for example) remux an ogg/theora file.
- * </para>
- * <para>
- * In addition, this element allows you to fix badly synchronized streams. You
- * pass in an array of (granule time, buffer time) synchronization points via
- * the synchronization-points GValueArray property, and this element will adjust
- * the granulepos values that it outputs. The adjustment will be made by
- * offsetting all buffers that it outputs by a specified amount, and updating
- * that offset from the value array whenever a keyframe is processed.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=video.ogg ! oggdemux ! theoraparse ! fakesink
- * </programlisting>
- * This pipeline shows that the streamheader is set in the caps, and that each
- * buffer has the timestamp, duration, offset, and offset_end set.
- * </para>
- * <para>
- * <programlisting>
- * gst-launch filesrc location=video.ogg ! oggdemux ! vorbisparse \
- * ! oggmux ! filesink location=video-remuxed.ogg
- * </programlisting>
- * This pipeline shows remuxing. video-remuxed.ogg might not be exactly the same
- * as video.ogg, but they should produce exactly the same decoded data.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-04-01 (0.10.4.1)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "gsttheoraparse.h"
-
-#define GST_CAT_DEFAULT theoraparse_debug
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
-
-static GstElementDetails theora_parse_details = {
- "Theora video parser",
- "Codec/Parser/Video",
- "parse raw theora streams",
- "Andy Wingo <wingo@pobox.com>"
-};
-
-static GstStaticPadTemplate theora_parse_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-theora")
- );
-
-static GstStaticPadTemplate theora_parse_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-theora")
- );
-
-enum
-{
- PROP_0,
- PROP_SYNCHRONIZATION_POINTS
-};
-
-GST_BOILERPLATE (GstTheoraParse, gst_theora_parse, GstElement,
- GST_TYPE_ELEMENT);
-
-static void theora_parse_dispose (GObject * object);
-static void theora_parse_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void theora_parse_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-
-static gboolean theora_parse_src_query (GstPad * pad, GstQuery * query);
-static GstFlowReturn theora_parse_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn theora_parse_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean theora_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean theora_parse_src_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_theora_parse_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_parse_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&theora_parse_sink_factory));
- gst_element_class_set_details (element_class, &theora_parse_details);
-}
-
-static void
-gst_theora_parse_class_init (GstTheoraParseClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->dispose = theora_parse_dispose;
- gobject_class->get_property = theora_parse_get_property;
- gobject_class->set_property = theora_parse_set_property;
-
- /**
- * GstTheoraParse:sychronization-points
- *
- * An array of (granuletime, buffertime) pairs
- *
- * Since: 0.10.10
- */
- g_object_class_install_property (gobject_class, PROP_SYNCHRONIZATION_POINTS,
- g_param_spec_value_array ("synchronization-points",
- "Synchronization points",
- "An array of (granuletime, buffertime) pairs",
- g_param_spec_uint64 ("time", "Time",
- "Time (either granuletime or buffertime)", 0, G_MAXUINT64, 0,
- G_PARAM_READWRITE), (GParamFlags) G_PARAM_READWRITE));
-
- gstelement_class->change_state = theora_parse_change_state;
-
- GST_DEBUG_CATEGORY_INIT (theoraparse_debug, "theoraparse", 0,
- "Theora parser");
-}
-
-static void
-gst_theora_parse_init (GstTheoraParse * parse, GstTheoraParseClass * g_class)
-{
- parse->sinkpad =
- gst_pad_new_from_static_template (&theora_parse_sink_factory, "sink");
- gst_pad_set_chain_function (parse->sinkpad, theora_parse_chain);
- gst_pad_set_event_function (parse->sinkpad, theora_parse_sink_event);
- gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
-
- parse->srcpad =
- gst_pad_new_from_static_template (&theora_parse_src_factory, "src");
- gst_pad_set_query_function (parse->srcpad, theora_parse_src_query);
- gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
-}
-
-static void
-theora_parse_dispose (GObject * object)
-{
- GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
- g_free (parse->times);
- parse->times = NULL;
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-theora_parse_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
- switch (prop_id) {
- case PROP_SYNCHRONIZATION_POINTS:
- {
- GValueArray *array;
- guint i;
-
- array = g_value_get_boxed (value);
-
- if (array) {
- if (array->n_values % 2)
- goto odd_values;
-
- g_free (parse->times);
- parse->times = g_new (GstClockTime, array->n_values);
- parse->npairs = array->n_values / 2;
- for (i = 0; i < array->n_values; i++)
- parse->times[i] = g_value_get_uint64 (&array->values[i]);
- } else {
- g_free (parse->times);
- parse->npairs = 0;
- }
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- return;
-
-odd_values:
- {
- g_critical ("expected an even number of time values for "
- "synchronization-points");
- return;
- }
-}
-
-static void
-theora_parse_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstTheoraParse *parse = GST_THEORA_PARSE (object);
-
- switch (prop_id) {
- case PROP_SYNCHRONIZATION_POINTS:
- {
- GValueArray *array = NULL;
- guint i;
-
- array = g_value_array_new (parse->npairs * 2);
-
- for (i = 0; i < parse->npairs; i++) {
- GValue v = { 0, };
-
- g_value_init (&v, G_TYPE_UINT64);
- g_value_set_uint64 (&v, parse->times[i * 2]);
- g_value_array_append (array, &v);
- g_value_set_uint64 (&v, parse->times[i * 2 + 1]);
- g_value_array_append (array, &v);
- g_value_unset (&v);
- }
-
- g_value_set_boxed (value, array);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-theora_parse_set_header_on_caps (GstTheoraParse * parse, GstCaps * caps)
-{
- GstBuffer **bufs;
- GstStructure *structure;
- gint i;
- GValue array = { 0 };
- GValue value = { 0 };
-
- bufs = parse->streamheader;
- structure = gst_caps_get_structure (caps, 0);
- g_value_init (&array, GST_TYPE_ARRAY);
-
- for (i = 0; i < 3; i++) {
- g_assert (bufs[i]);
- bufs[i] = gst_buffer_make_metadata_writable (bufs[i]);
- GST_BUFFER_FLAG_SET (bufs[i], GST_BUFFER_FLAG_IN_CAPS);
-
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, bufs[i]);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- }
-
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&array);
-}
-
-/* FIXME: copy from libtheora, theora should somehow make this available for seeking */
-static int
-_theora_ilog (unsigned int v)
-{
- int ret = 0;
-
- while (v) {
- ret++;
- v >>= 1;
- }
- return (ret);
-}
-
-/* two tasks to do here: set the streamheader on the caps, and use libtheora to
- parse the headers */
-static void
-theora_parse_set_streamheader (GstTheoraParse * parse)
-{
- GstCaps *caps;
- gint i;
- guint32 bitstream_version;
-
- g_assert (!parse->streamheader_received);
-
- caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad));
- theora_parse_set_header_on_caps (parse, caps);
- GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
- gst_pad_set_caps (parse->srcpad, caps);
- gst_caps_unref (caps);
-
- for (i = 0; i < 3; i++) {
- ogg_packet packet;
- GstBuffer *buf;
-
- buf = parse->streamheader[i];
- gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- packet.packetno = i + 1;
- packet.e_o_s = 0;
- theora_decode_header (&parse->info, &parse->comment, &packet);
- }
-
- parse->fps_n = parse->info.fps_numerator;
- parse->fps_d = parse->info.fps_denominator;
- parse->shift = _theora_ilog (parse->info.keyframe_frequency_force - 1);
-
- /* With libtheora-1.0beta1 the granulepos scheme was changed:
- * where earlier the granulepos refered to the index/beginning
- * of a frame, it now refers to the end, which matches the use
- * in vorbis/speex. We check the bitstream version from the header so
- * we know which way to interpret the incoming granuepos
- */
- bitstream_version = (parse->info.version_major << 16) |
- (parse->info.version_minor << 8) | parse->info.version_subminor;
- parse->is_old_bitstream = (bitstream_version <= 0x00030200);
-
- parse->streamheader_received = TRUE;
-}
-
-static void
-theora_parse_drain_event_queue (GstTheoraParse * parse)
-{
- while (parse->event_queue->length) {
- GstEvent *event;
-
- event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
- gst_pad_event_default (parse->sinkpad, event);
- }
-}
-
-static void
-theora_parse_push_headers (GstTheoraParse * parse)
-{
- gint i;
-
- theora_parse_drain_event_queue (parse);
-
- if (!parse->streamheader_received)
- theora_parse_set_streamheader (parse);
-
- /* ignore return values, we pass along the result of pushing data packets only
- */
- for (i = 0; i < 3; i++)
- gst_pad_push (parse->srcpad, gst_buffer_ref (parse->streamheader[i]));
-
- parse->send_streamheader = FALSE;
-}
-
-static void
-theora_parse_clear_queue (GstTheoraParse * parse)
-{
- while (parse->buffer_queue->length) {
- GstBuffer *buf;
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
- gst_buffer_unref (buf);
- }
- while (parse->event_queue->length) {
- GstEvent *event;
-
- event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
- gst_buffer_unref (event);
- }
-}
-
-static gint64
-make_granulepos (GstTheoraParse * parse, gint64 keyframe, gint64 frame)
-{
- if (keyframe == -1)
- keyframe = 0;
- /* If using newer theora, offset the granulepos by +1, see comment
- * in theora_parse_set_streamheader */
- if (!parse->is_old_bitstream)
- keyframe += 1;
-
- g_return_val_if_fail (frame >= keyframe, -1);
- g_return_val_if_fail (frame - keyframe < 1 << parse->shift, -1);
-
- return (keyframe << parse->shift) + (frame - keyframe);
-}
-
-static void
-parse_granulepos (GstTheoraParse * parse, gint64 granulepos,
- gint64 * keyframe, gint64 * frame)
-{
- gint64 kf;
-
- kf = granulepos >> parse->shift;
- /* If using newer theora, offset the granulepos by -1, see comment
- * in theora_parse_set_streamheader */
- if (!parse->is_old_bitstream)
- kf -= 1;
- if (keyframe)
- *keyframe = kf;
- if (frame)
- *frame = kf + (granulepos & ((1 << parse->shift) - 1));
-}
-
-static gboolean
-is_keyframe (GstBuffer * buf)
-{
- if (!GST_BUFFER_DATA (buf))
- return FALSE;
- if (!GST_BUFFER_SIZE (buf))
- return FALSE;
- return ((GST_BUFFER_DATA (buf)[0] & 0x40) == 0);
-}
-
-static void
-theora_parse_munge_granulepos (GstTheoraParse * parse, GstBuffer * buf,
- gint64 keyframe, gint64 frame)
-{
- gint64 frames_diff;
- GstClockTimeDiff time_diff;
-
- if (keyframe == frame) {
- gint i;
-
- /* update granule_offset */
- for (i = 0; i < parse->npairs; i++) {
- if (parse->times[i * 2] >= GST_BUFFER_OFFSET (buf))
- break;
- }
- if (i > 0) {
- /* time_diff gets reset below */
- time_diff = parse->times[i * 2 - 1] - parse->times[i * 2 - 2];
- parse->granule_offset = gst_util_uint64_scale (time_diff,
- parse->fps_n, parse->fps_d * GST_SECOND);
- parse->granule_offset <<= parse->shift;
- }
- }
-
- frames_diff = parse->granule_offset >> parse->shift;
- time_diff = gst_util_uint64_scale_int (GST_SECOND * frames_diff,
- parse->fps_d, parse->fps_n);
-
- GST_DEBUG_OBJECT (parse, "offsetting theora stream by %" G_GINT64_FORMAT
- " frames (%" GST_TIME_FORMAT ")", frames_diff, GST_TIME_ARGS (time_diff));
-
- GST_BUFFER_OFFSET_END (buf) += parse->granule_offset;
- GST_BUFFER_OFFSET (buf) += time_diff;
- GST_BUFFER_TIMESTAMP (buf) += time_diff;
-}
-
-static GstFlowReturn
-theora_parse_push_buffer (GstTheoraParse * parse, GstBuffer * buf,
- gint64 keyframe, gint64 frame)
-{
-
- GstClockTime this_time, next_time;
-
- this_time = gst_util_uint64_scale_int (GST_SECOND * frame,
- parse->fps_d, parse->fps_n);
-
- next_time = gst_util_uint64_scale_int (GST_SECOND * (frame + 1),
- parse->fps_d, parse->fps_n);
-
- GST_BUFFER_OFFSET_END (buf) = make_granulepos (parse, keyframe, frame);
- GST_BUFFER_OFFSET (buf) = this_time;
- GST_BUFFER_TIMESTAMP (buf) = this_time;
- GST_BUFFER_DURATION (buf) = next_time - this_time;
-
- gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
- if (parse->times)
- theora_parse_munge_granulepos (parse, buf, keyframe, frame);
-
- GST_DEBUG_OBJECT (parse, "pushing buffer with granulepos %" G_GINT64_FORMAT
- "|%" G_GINT64_FORMAT, keyframe, frame - keyframe);
-
- return gst_pad_push (parse->srcpad, buf);
-}
-
-static GstFlowReturn
-theora_parse_drain_queue_prematurely (GstTheoraParse * parse)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- /* got an EOS event, make sure to push out any buffers that were in the queue
- * -- won't normally be the case, but this catches the
- * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous
- * stream. */
-
- GST_DEBUG_OBJECT (parse, "got EOS, draining queue");
-
- /* if we get an eos before pushing the streamheaders, drain our events before
- * eos */
- theora_parse_drain_event_queue (parse);
-
- while (!g_queue_is_empty (parse->buffer_queue)) {
- GstBuffer *buf;
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
- parse->prev_frame++;
-
- if (is_keyframe (buf))
- /* we have a keyframe */
- parse->prev_keyframe = parse->prev_frame;
- else
- GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT;
-
- if (parse->prev_keyframe < 0) {
- if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
- parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
- &parse->prev_keyframe, NULL);
- } else {
- /* No previous keyframe known; can't extract one from this frame. That
- * means we can't do any valid output for this frame, just continue to
- * the next frame.
- */
- gst_buffer_unref (buf);
- continue;
- }
- }
-
- ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe,
- parse->prev_frame);
-
- if (ret != GST_FLOW_OK)
- goto done;
- }
-
-done:
- return ret;
-}
-
-static GstFlowReturn
-theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- gint64 keyframe, prev_frame, frame;
-
- parse_granulepos (parse, granulepos, &keyframe, &frame);
-
- prev_frame = frame - g_queue_get_length (parse->buffer_queue);
- if (prev_frame < parse->prev_frame) {
- GST_WARNING ("jumped %" G_GINT64_FORMAT
- " frames backwards! not sure what to do here",
- parse->prev_frame - prev_frame);
- ret = GST_FLOW_ERROR;
- goto done;
- } else if (prev_frame > parse->prev_frame) {
- GST_INFO ("discontinuity detected (%" G_GINT64_FORMAT
- " frames)", prev_frame - parse->prev_frame);
- if (keyframe <= prev_frame && keyframe > parse->prev_keyframe)
- parse->prev_keyframe = keyframe;
- parse->prev_frame = prev_frame;
- }
-
- GST_DEBUG ("draining queue of length %d",
- g_queue_get_length (parse->buffer_queue));
-
- while (!g_queue_is_empty (parse->buffer_queue)) {
- GstBuffer *buf;
-
- parse->prev_frame++;
- g_assert (parse->prev_frame >= 0);
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
- if (is_keyframe (buf))
- /* we have a keyframe */
- parse->prev_keyframe = parse->prev_frame;
- else
- GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT;
-
- ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe,
- parse->prev_frame);
-
- if (ret != GST_FLOW_OK)
- goto done;
- }
-
-done:
- return ret;
-}
-
-static GstFlowReturn
-theora_parse_queue_buffer (GstTheoraParse * parse, GstBuffer * buf)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- buf = gst_buffer_make_metadata_writable (buf);
-
- g_queue_push_tail (parse->buffer_queue, buf);
-
- if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) {
- if (parse->prev_keyframe < 0) {
- parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf),
- &parse->prev_keyframe, NULL);
- }
- ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
- }
-
- return ret;
-}
-
-static GstFlowReturn
-theora_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstFlowReturn ret;
- GstBuffer *buf;
- GstTheoraParse *parse;
-
- parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
- buf = GST_BUFFER (buffer);
- parse->packetno++;
-
- if (parse->packetno <= 3) {
- /* if 1 <= packetno <= 3, it's streamheader,
- * so put it on the streamheader list and return */
- parse->streamheader[parse->packetno - 1] = buf;
- ret = GST_FLOW_OK;
- } else {
- if (parse->send_streamheader)
- theora_parse_push_headers (parse);
-
- ret = theora_parse_queue_buffer (parse, buf);
- }
-
- gst_object_unref (parse);
-
- return ret;
-}
-
-static gboolean
-theora_parse_queue_event (GstTheoraParse * parse, GstEvent * event)
-{
- g_queue_push_tail (parse->event_queue, event);
- return TRUE;
-}
-
-static gboolean
-theora_parse_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret;
- GstTheoraParse *parse;
-
- parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- theora_parse_clear_queue (parse);
- parse->prev_keyframe = -1;
- parse->prev_frame = -1;
- ret = gst_pad_event_default (pad, event);
- break;
- case GST_EVENT_EOS:
- theora_parse_drain_queue_prematurely (parse);
- ret = gst_pad_event_default (pad, event);
- break;
- default:
- if (parse->send_streamheader && GST_EVENT_IS_SERIALIZED (event))
- ret = theora_parse_queue_event (parse, event);
- else
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (parse);
-
- return ret;
-}
-
-static gboolean
-theora_parse_src_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstTheoraParse *parse;
- guint64 scale = 1;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
- /* we need the info part before we can done something */
- if (!parse->streamheader_received)
- goto no_header;
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- *dest_value = gst_util_uint64_scale_int (src_value, 2,
- parse->info.height * parse->info.width * 3);
- break;
- case GST_FORMAT_TIME:
- /* seems like a rather silly conversion, implement me if you like */
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- scale = 3 * (parse->info.width * parse->info.height) / 2;
- case GST_FORMAT_DEFAULT:
- *dest_value = scale * gst_util_uint64_scale (src_value,
- parse->info.fps_numerator,
- parse->info.fps_denominator * GST_SECOND);
- break;
- default:
- GST_DEBUG_OBJECT (parse, "cannot convert to format %s",
- gst_format_get_name (*dest_format));
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = gst_util_uint64_scale (src_value,
- GST_SECOND * parse->info.fps_denominator,
- parse->info.fps_numerator);
- break;
- case GST_FORMAT_BYTES:
- *dest_value = gst_util_uint64_scale_int (src_value,
- 3 * parse->info.width * parse->info.height, 2);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-done:
- gst_object_unref (parse);
- return res;
-
- /* ERRORS */
-no_header:
- {
- GST_DEBUG_OBJECT (parse, "no header yet, cannot convert");
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-theora_parse_src_query (GstPad * pad, GstQuery * query)
-{
- GstTheoraParse *parse;
-
- gboolean res = FALSE;
-
- parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 frame, value;
- GstFormat my_format, format;
- gint64 time;
-
- frame = parse->prev_frame;
-
- GST_LOG_OBJECT (parse,
- "query %p: we have current frame: %lld", query, frame);
-
- /* parse format */
- gst_query_parse_position (query, &format, NULL);
-
- /* and convert to the final format in two steps with time as the
- * intermediate step */
- my_format = GST_FORMAT_TIME;
- if (!(res =
- theora_parse_src_convert (parse->sinkpad, GST_FORMAT_DEFAULT,
- frame, &my_format, &time)))
- goto error;
-
- /* fixme: handle segments
- time = (time - parse->segment.start) + parse->segment.time;
- */
-
- GST_LOG_OBJECT (parse,
- "query %p: our time: %" GST_TIME_FORMAT " (conv to %s)",
- query, GST_TIME_ARGS (time), gst_format_get_name (format));
-
- if (!(res =
- theora_parse_src_convert (pad, my_format, time, &format, &value)))
- goto error;
-
- gst_query_set_position (query, format, value);
-
- GST_LOG_OBJECT (parse,
- "query %p: we return %lld (format %u)", query, value, format);
-
- break;
- }
- case GST_QUERY_DURATION:
- /* forward to peer for total */
- if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query)))
- goto error;
- break;
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- theora_parse_src_convert (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
-
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-done:
- gst_object_unref (parse);
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (parse, "query failed");
- goto done;
- }
-}
-
-static GstStateChangeReturn
-theora_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstTheoraParse *parse = GST_THEORA_PARSE (element);
- GstStateChangeReturn ret;
- gint i;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- theora_info_init (&parse->info);
- theora_comment_init (&parse->comment);
- parse->packetno = 0;
- parse->send_streamheader = TRUE;
- parse->buffer_queue = g_queue_new ();
- parse->event_queue = g_queue_new ();
- parse->prev_keyframe = -1;
- parse->prev_frame = -1;
- parse->granule_offset = 0;
- break;
- default:
- break;
- }
-
- ret = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- theora_info_clear (&parse->info);
- theora_comment_clear (&parse->comment);
- theora_parse_clear_queue (parse);
- g_queue_free (parse->buffer_queue);
- g_queue_free (parse->event_queue);
- parse->buffer_queue = NULL;
- for (i = 0; i < 3; i++) {
- if (parse->streamheader[i]) {
- gst_buffer_unref (parse->streamheader[i]);
- parse->streamheader[i] = NULL;
- }
- }
- parse->streamheader_received = FALSE;
- break;
- default:
- break;
- }
-
- return ret;
-}
--- a/gst_plugins_base/ext/vorbis/vorbis.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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 "gst/tag/tag.h"
-
-#include "vorbisenc.h"
-#include "vorbisdec.h"
-#include "vorbisparse.h"
-#include "vorbistag.h"
-
-GST_DEBUG_CATEGORY (vorbisenc_debug);
-GST_DEBUG_CATEGORY (vorbisdec_debug);
-GST_DEBUG_CATEGORY (vorbisparse_debug);
-GST_DEBUG_CATEGORY (vorbistag_debug);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "vorbisenc", GST_RANK_NONE,
- GST_TYPE_VORBISENC))
- return FALSE;
-
- if (!gst_element_register (plugin, "vorbisdec", GST_RANK_PRIMARY,
- gst_vorbis_dec_get_type ()))
- return FALSE;
-
- if (!gst_element_register (plugin, "vorbisparse", GST_RANK_NONE,
- gst_vorbis_parse_get_type ()))
- return FALSE;
-
- if (!gst_element_register (plugin, "vorbistag", GST_RANK_NONE,
- gst_vorbis_tag_get_type ()))
- return FALSE;
-
- GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0,
- "vorbis encoding element");
- GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "vorbisdec", 0,
- "vorbis decoding element");
- GST_DEBUG_CATEGORY_INIT (vorbisparse_debug, "vorbisparse", 0,
- "vorbis parsing element");
- GST_DEBUG_CATEGORY_INIT (vorbistag_debug, "vorbistag", 0,
- "vorbis tagging element");
-
- gst_tag_register_musicbrainz_tags ();
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "vorbis",
- "Vorbis plugin library",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/ext/vorbis/vorbisdec.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1408 +0,0 @@
-/* GStreamer
- * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
- *
- * 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.
- */
-
-/**
- * SECTION:element-vorbisdec
- * @short_description: a decoder that decodes Vorbis to raw audio
- * @see_also: vorbisenc, oggdemux
- *
- * <refsect2>
- * <para>
- * This element decodes a Vorbis stream to raw float audio.
- * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
- * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
- * </programlisting>
- * Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "vorbisdec.h"
-#include <string.h>
-#include <gst/audio/audio.h>
-#include <gst/tag/tag.h>
-#include <gst/audio/multichannel.h>
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug);
-#define GST_CAT_DEFAULT vorbisdec_debug
-
-static const GstElementDetails vorbis_dec_details =
-GST_ELEMENT_DETAILS ("Vorbis audio decoder",
- "Codec/Decoder/Audio",
- "decode raw vorbis streams to float audio",
- "Benjamin Otte <in7y118@public.uni-hamburg.de>");
-
-static GstStaticPadTemplate vorbis_dec_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw-float, "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, "
-/* no ifdef in macros, please
-#ifdef GST_VORBIS_DEC_SEQUENTIAL
- "layout = \"sequential\", "
-#endif
-*/
- "width = (int) 32")
- );
-
-static GstStaticPadTemplate vorbis_dec_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-vorbis")
- );
-
-GST_BOILERPLATE (GstVorbisDec, gst_vorbis_dec, GstElement, GST_TYPE_ELEMENT);
-
-static void vorbis_dec_finalize (GObject * object);
-static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer);
-static GstFlowReturn vorbis_dec_chain_forward (GstVorbisDec * vd,
- gboolean discont, GstBuffer * buffer);
-static GstStateChangeReturn vorbis_dec_change_state (GstElement * element,
- GstStateChange transition);
-
-static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event);
-static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query);
-static gboolean vorbis_dec_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value);
-
-static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query);
-
-static void
-gst_vorbis_dec_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- GstPadTemplate *src_template, *sink_template;
-
- src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
- gst_element_class_add_pad_template (element_class, src_template);
-
- sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory);
- gst_element_class_add_pad_template (element_class, sink_template);
-
- gst_element_class_set_details (element_class, &vorbis_dec_details);
-}
-
-static void
-gst_vorbis_dec_class_init (GstVorbisDecClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gobject_class->finalize = vorbis_dec_finalize;
-
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state);
-}
-
-static const GstQueryType *
-vorbis_get_query_types (GstPad * pad)
-{
- static const GstQueryType vorbis_dec_src_query_types[] = {
- GST_QUERY_POSITION,
- GST_QUERY_DURATION,
- GST_QUERY_CONVERT,
- 0
- };
-
- return vorbis_dec_src_query_types;
-}
-
-static void
-gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class)
-{
- dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory,
- "sink");
-
- gst_pad_set_event_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (vorbis_dec_sink_event));
- gst_pad_set_chain_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (vorbis_dec_chain));
- gst_pad_set_query_function (dec->sinkpad,
- GST_DEBUG_FUNCPTR (vorbis_dec_sink_query));
- gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
-
- dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory,
- "src");
-
- gst_pad_set_event_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (vorbis_dec_src_event));
- gst_pad_set_query_type_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (vorbis_get_query_types));
- gst_pad_set_query_function (dec->srcpad,
- GST_DEBUG_FUNCPTR (vorbis_dec_src_query));
- gst_pad_use_fixed_caps (dec->srcpad);
- gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
-
- dec->queued = NULL;
- dec->pendingevents = NULL;
- dec->taglist = NULL;
-}
-
-static void
-vorbis_dec_finalize (GObject * object)
-{
- /* Release any possibly allocated libvorbis data.
- * _clear functions can safely be called multiple times
- */
- GstVorbisDec *vd = GST_VORBIS_DEC (object);
-
- vorbis_block_clear (&vd->vb);
- vorbis_dsp_clear (&vd->vd);
- vorbis_comment_clear (&vd->vc);
- vorbis_info_clear (&vd->vi);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_vorbis_dec_reset (GstVorbisDec * dec)
-{
- dec->cur_timestamp = GST_CLOCK_TIME_NONE;
- dec->prev_timestamp = GST_CLOCK_TIME_NONE;
- dec->granulepos = -1;
- dec->discont = TRUE;
- gst_segment_init (&dec->segment, GST_FORMAT_TIME);
-
- g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->queued);
- dec->queued = NULL;
- g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->gather);
- dec->gather = NULL;
- g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->decode);
- dec->decode = NULL;
- g_list_foreach (dec->pendingevents, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (dec->pendingevents);
- dec->pendingevents = NULL;
-
- if (dec->taglist)
- gst_tag_list_free (dec->taglist);
- dec->taglist = NULL;
-}
-
-
-static gboolean
-vorbis_dec_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstVorbisDec *dec;
- guint64 scale = 1;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- if (!dec->initialized)
- goto no_header;
-
- if (dec->sinkpad == pad &&
- (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
- goto no_format;
-
- switch (src_format) {
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- scale = sizeof (float) * dec->vi.channels;
- case GST_FORMAT_DEFAULT:
- *dest_value =
- scale * gst_util_uint64_scale_int (src_value, dec->vi.rate,
- GST_SECOND);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * sizeof (float) * dec->vi.channels;
- break;
- case GST_FORMAT_TIME:
- *dest_value =
- gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value / (sizeof (float) * dec->vi.channels);
- break;
- case GST_FORMAT_TIME:
- *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
- dec->vi.rate * sizeof (float) * dec->vi.channels);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-no_header:
- {
- GST_DEBUG_OBJECT (dec, "no header packets received");
- res = FALSE;
- goto done;
- }
-no_format:
- {
- GST_DEBUG_OBJECT (dec, "formats unsupported");
- res = FALSE;
- goto done;
- }
-}
-
-static gboolean
-vorbis_dec_src_query (GstPad * pad, GstQuery * query)
-{
- GstVorbisDec *dec;
- gboolean res = FALSE;
-
- dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- gint64 granulepos, value;
- GstFormat my_format, format;
- gint64 time;
-
- /* we start from the last seen granulepos */
- granulepos = dec->granulepos;
-
- gst_query_parse_position (query, &format, NULL);
-
- /* and convert to the final format in two steps with time as the
- * intermediate step */
- my_format = GST_FORMAT_TIME;
- if (!(res =
- vorbis_dec_convert (pad, GST_FORMAT_DEFAULT, granulepos,
- &my_format, &time)))
- goto error;
-
- /* correct for the segment values */
- time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
-
- GST_LOG_OBJECT (dec,
- "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
-
- /* and convert to the final format */
- if (!(res = vorbis_dec_convert (pad, my_format, time, &format, &value)))
- goto error;
-
- gst_query_set_position (query, format, value);
-
- GST_LOG_OBJECT (dec,
- "query %p: we return %lld (format %u)", query, value, format);
-
- break;
- }
- case GST_QUERY_DURATION:
- {
- GstPad *peer;
-
- if (!(peer = gst_pad_get_peer (dec->sinkpad))) {
- GST_WARNING_OBJECT (dec, "sink pad %" GST_PTR_FORMAT " is not linked",
- dec->sinkpad);
- goto error;
- }
-
- res = gst_pad_query (peer, query);
- gst_object_unref (peer);
- if (!res)
- goto error;
-
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
- goto error;
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_WARNING_OBJECT (dec, "error handling query");
- goto done;
- }
-}
-
-static gboolean
-vorbis_dec_sink_query (GstPad * pad, GstQuery * query)
-{
- GstVorbisDec *dec;
- gboolean res;
-
- dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
- goto error;
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-error:
- {
- GST_DEBUG_OBJECT (dec, "error converting value");
- goto done;
- }
-}
-
-static gboolean
-vorbis_dec_src_event (GstPad * pad, GstEvent * event)
-{
- gboolean res = TRUE;
- GstVorbisDec *dec;
-
- dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:
- {
- GstFormat format, tformat;
- gdouble rate;
- GstEvent *real_seek;
- GstSeekFlags flags;
- GstSeekType cur_type, stop_type;
- gint64 cur, stop;
- gint64 tcur, tstop;
-
- gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
- &stop_type, &stop);
- gst_event_unref (event);
-
- /* we have to ask our peer to seek to time here as we know
- * nothing about how to generate a granulepos from the src
- * formats or anything.
- *
- * First bring the requested format to time
- */
- tformat = GST_FORMAT_TIME;
- if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
- goto convert_error;
- if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
- goto convert_error;
-
- /* then seek with time on the peer */
- real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
- flags, cur_type, tcur, stop_type, tstop);
-
- res = gst_pad_push_event (dec->sinkpad, real_seek);
-
- break;
- }
- default:
- res = gst_pad_push_event (dec->sinkpad, event);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return res;
-
- /* ERRORS */
-convert_error:
- {
- GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
- goto done;
- }
-}
-
-static gboolean
-vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret = FALSE;
- GstVorbisDec *dec;
-
- dec = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (dec, "handling event");
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_FLUSH_START:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_FLUSH_STOP:
- /* here we must clean any state in the decoder */
-#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
- vorbis_synthesis_restart (&dec->vd);
-#endif
- gst_vorbis_dec_reset (dec);
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat format;
- gdouble rate, arate;
- gint64 start, stop, time;
- gboolean update;
-
- gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
- &start, &stop, &time);
-
- /* we need time for now */
- if (format != GST_FORMAT_TIME)
- goto newseg_wrong_format;
-
- GST_DEBUG_OBJECT (dec,
- "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT
- ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT,
- update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
- GST_TIME_ARGS (time));
-
- /* now configure the values */
- gst_segment_set_newsegment_full (&dec->segment, update,
- rate, arate, format, start, stop, time);
-
- if (dec->initialized)
- /* and forward */
- ret = gst_pad_push_event (dec->srcpad, event);
- else {
- /* store it to send once we're initialized */
- dec->pendingevents = g_list_append (dec->pendingevents, event);
- ret = TRUE;
- }
- break;
- }
- default:
- ret = gst_pad_push_event (dec->srcpad, event);
- break;
- }
-done:
- gst_object_unref (dec);
-
- return ret;
-
- /* ERRORS */
-newseg_wrong_format:
- {
- GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
- goto done;
- }
-}
-
-static GstFlowReturn
-vorbis_handle_identification_packet (GstVorbisDec * vd)
-{
- GstCaps *caps;
- const GstAudioChannelPosition *pos = NULL;
-
- switch (vd->vi.channels) {
- case 1:
- case 2:
- /* nothing */
- break;
- case 3:{
- static const GstAudioChannelPosition pos3[] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
- };
- pos = pos3;
- break;
- }
- case 4:{
- static const GstAudioChannelPosition pos4[] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
- };
- pos = pos4;
- break;
- }
- case 5:{
- static const GstAudioChannelPosition pos5[] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
- };
- pos = pos5;
- break;
- }
- case 6:{
- static const GstAudioChannelPosition pos6[] = {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_LFE
- };
- pos = pos6;
- break;
- }
- default:
- goto channel_count_error;
- }
-
- caps = gst_caps_new_simple ("audio/x-raw-float",
- "rate", G_TYPE_INT, vd->vi.rate,
- "channels", G_TYPE_INT, vd->vi.channels,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
-
- if (pos) {
- gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
- }
- gst_pad_set_caps (vd->srcpad, caps);
- gst_caps_unref (caps);
-
- return GST_FLOW_OK;
-
- /* ERROR */
-channel_count_error:
- {
- GST_ELEMENT_ERROR (vd, STREAM, NOT_IMPLEMENTED, (NULL),
- ("Unsupported channel count %d", vd->vi.channels));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
- guint bitrate = 0;
- gchar *encoder = NULL;
- GstTagList *list;
- GstBuffer *buf;
-
- GST_DEBUG_OBJECT (vd, "parsing comment packet");
-
- buf = gst_buffer_new_and_alloc (packet->bytes);
- GST_BUFFER_DATA (buf) = packet->packet;
-
- list =
- gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
- &encoder);
-
- vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
-
- gst_tag_list_free (list);
- gst_buffer_unref (buf);
-
- if (!vd->taglist) {
- GST_ERROR_OBJECT (vd, "couldn't decode comments");
- vd->taglist = gst_tag_list_new ();
- }
- if (encoder) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_ENCODER, encoder, NULL);
- g_free (encoder);
- }
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_ENCODER_VERSION, vd->vi.version,
- GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
- if (vd->vi.bitrate_nominal > 0) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
- bitrate = vd->vi.bitrate_nominal;
- }
- if (vd->vi.bitrate_upper > 0) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
- if (!bitrate)
- bitrate = vd->vi.bitrate_upper;
- }
- if (vd->vi.bitrate_lower > 0) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
- if (!bitrate)
- bitrate = vd->vi.bitrate_lower;
- }
- if (bitrate) {
- gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
- GST_TAG_BITRATE, (guint) bitrate, NULL);
- }
-
- if (vd->initialized) {
- gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad,
- vd->taglist);
- vd->taglist = NULL;
- } else {
- /* Only post them as messages for the time being. *
- * They will be pushed on the pad once the decoder is initialized */
- gst_element_post_message (GST_ELEMENT_CAST (vd),
- gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
- }
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-vorbis_handle_type_packet (GstVorbisDec * vd)
-{
- GList *walk;
-
- g_assert (vd->initialized == FALSE);
-
- vorbis_synthesis_init (&vd->vd, &vd->vi);
- vorbis_block_init (&vd->vd, &vd->vb);
- vd->initialized = TRUE;
-
- if (vd->pendingevents) {
- for (walk = vd->pendingevents; walk; walk = g_list_next (walk))
- gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data));
- g_list_free (vd->pendingevents);
- vd->pendingevents = NULL;
- }
-
- if (vd->taglist) {
- /* The tags have already been sent on the bus as messages. */
- gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist));
- vd->taglist = NULL;
- }
-
- return GST_FLOW_OK;
-}
-
-static GstFlowReturn
-vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
- GstFlowReturn res;
-
- GST_DEBUG_OBJECT (vd, "parsing header packet");
-
- /* Packetno = 0 if the first byte is exactly 0x01 */
- packet->b_o_s = (packet->packet[0] == 0x1) ? 1 : 0;
-
- if (vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet))
- goto header_read_error;
-
- switch (packet->packet[0]) {
- case 0x01:
- res = vorbis_handle_identification_packet (vd);
- break;
- case 0x03:
- res = vorbis_handle_comment_packet (vd, packet);
- break;
- case 0x05:
- res = vorbis_handle_type_packet (vd);
- break;
- default:
- /* ignore */
- g_warning ("unknown vorbis header packet found");
- res = GST_FLOW_OK;
- break;
- }
- return res;
-
- /* ERRORS */
-header_read_error:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
- (NULL), ("couldn't read header packet"));
- return GST_FLOW_ERROR;
- }
-}
-
-/* These samples can be outside of the float -1.0 -- 1.0 range, this
- * is allowed, downstream elements are supposed to clip */
-static void
-copy_samples (float *out, float **in, guint samples, gint channels)
-{
- gint i, j;
-
-#ifdef GST_VORBIS_DEC_SEQUENTIAL
- for (i = 0; i < channels; i++) {
- memcpy (out, in[i], samples * sizeof (float));
- out += samples;
- }
-#else
- for (j = 0; j < samples; j++) {
- for (i = 0; i < channels; i++) {
- *out++ = in[i][j];
- }
- }
-#endif
-}
-
-static GstFlowReturn
-vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf)
-{
- GstFlowReturn result;
- gint64 outoffset, origoffset;
-
- origoffset = GST_BUFFER_OFFSET (buf);
-
-again:
- outoffset = origoffset;
-
- if (outoffset == -1) {
- dec->queued = g_list_append (dec->queued, buf);
- GST_DEBUG_OBJECT (dec, "queued buffer");
- result = GST_FLOW_OK;
- } else {
- if (G_UNLIKELY (dec->queued)) {
- guint size;
- GstClockTime ts;
- GList *walk;
-
- GST_DEBUG_OBJECT (dec, "first buffer with offset %lld", outoffset);
- ts = gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
-
- size = g_list_length (dec->queued);
- /* we walk the queued up list in reverse, and set the buffer fields
- * calculating backwards */
- for (walk = g_list_last (dec->queued); walk;
- walk = g_list_previous (walk)) {
- GstBuffer *buffer = GST_BUFFER (walk->data);
- guint offset;
-
- offset = GST_BUFFER_SIZE (buffer) / (sizeof (float) * dec->vi.channels);
-
- if (outoffset >= offset)
- outoffset -= offset;
- else {
- /* we can't go below 0, this means this first offset was at the eos
- * page and we need to clip to it instead */
- GST_DEBUG_OBJECT (dec, "clipping %" G_GINT64_FORMAT,
- offset - outoffset);
- origoffset += (offset - outoffset);
- goto again;
- }
-
- GST_BUFFER_OFFSET (buffer) = outoffset;
- GST_BUFFER_TIMESTAMP (buffer) =
- gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
- GST_BUFFER_DURATION (buffer) = GST_CLOCK_DIFF (GST_BUFFER_TIMESTAMP
- (buffer), ts);
- ts = GST_BUFFER_TIMESTAMP (buffer);
- GST_DEBUG_OBJECT (dec, "patch buffer %u, offset %" G_GUINT64_FORMAT
- ", timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT,
- size, outoffset,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
- size--;
- }
- for (walk = dec->queued; walk; walk = g_list_next (walk)) {
- GstBuffer *buffer = GST_BUFFER (walk->data);
-
- /* clips to the configured segment, or returns NULL with buffer
- * unreffed when the input buffer is completely outside the segment */
- if (!(buffer = gst_audio_buffer_clip (buffer, &dec->segment,
- dec->vi.rate, dec->vi.channels * sizeof (float))))
- continue;
-
- if (dec->discont) {
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- dec->discont = FALSE;
- }
- /* ignore the result */
- gst_pad_push (dec->srcpad, buffer);
- }
- g_list_free (dec->queued);
- dec->queued = NULL;
- }
-
- /* clip */
- if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
- dec->vi.channels * sizeof (float))))
- return GST_FLOW_OK;
-
- if (dec->discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- dec->discont = FALSE;
- }
-
- result = gst_pad_push (dec->srcpad, buf);
- }
-
- return result;
-}
-
-static GstFlowReturn
-vorbis_dec_push_reverse (GstVorbisDec * dec, GstBuffer * buf)
-{
- GstFlowReturn result = GST_FLOW_OK;
-
- dec->queued = g_list_prepend (dec->queued, buf);
-
- return result;
-}
-
-static GstFlowReturn
-vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet)
-{
- float **pcm;
- guint sample_count;
- GstBuffer *out;
- GstFlowReturn result;
- GstClockTime timestamp = GST_CLOCK_TIME_NONE, nextts;
- gint size;
-
- if (!vd->initialized)
- goto not_initialized;
-
- /* FIXME, we should queue undecoded packets here until we get
- * a timestamp, then we reverse timestamp the queued packets and
- * clip them, then we decode only the ones we want and don't
- * keep decoded data in memory.
- * Ideally, of course, the demuxer gives us a valid timestamp on
- * the first packet.
- */
-
- /* normal data packet */
- /* FIXME, we can skip decoding if the packet is outside of the
- * segment, this is however not very trivial as we need a previous
- * packet to decode the current one so we must be carefull not to
- * throw away too much. For now we decode everything and clip right
- * before pushing data. */
- if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet)))
- goto could_not_read;
-
- if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0))
- goto not_accepted;
-
- /* assume all goes well here */
- result = GST_FLOW_OK;
-
- /* count samples ready for reading */
- if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0)
- goto done;
-
- GST_LOG_OBJECT (vd, "%d samples ready for reading", sample_count);
- size = sample_count * vd->vi.channels * sizeof (float);
-
- /* alloc buffer for it */
- result =
- gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE,
- size, GST_PAD_CAPS (vd->srcpad), &out);
- if (G_UNLIKELY (result != GST_FLOW_OK))
- goto done;
-
- /* get samples ready for reading now, should be sample_count */
- if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count))
- goto wrong_samples;
-
- /* copy samples in buffer */
- copy_samples ((float *) GST_BUFFER_DATA (out), pcm, sample_count,
- vd->vi.channels);
-
- GST_BUFFER_SIZE (out) = size;
-
- /* this should not overflow */
- GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;
-
- if (packet->granulepos != -1)
- vd->granulepos = packet->granulepos - sample_count;
-
- if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) {
- /* we have incoming timestamps */
- timestamp = vd->cur_timestamp;
- GST_DEBUG_OBJECT (vd,
- "cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = %"
- GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp),
- GST_TIME_ARGS (GST_BUFFER_DURATION (out)),
- GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out)));
- vd->cur_timestamp += GST_BUFFER_DURATION (out);
- GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp,
- vd->vi.rate);
- GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count;
- } else {
- /* we have incoming granulepos */
- GST_BUFFER_OFFSET (out) = vd->granulepos;
- if (vd->granulepos != -1) {
- GST_DEBUG_OBJECT (vd, "granulepos: %" G_GINT64_FORMAT, vd->granulepos);
- GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count;
- timestamp =
- gst_util_uint64_scale_int (vd->granulepos, GST_SECOND, vd->vi.rate);
- nextts =
- gst_util_uint64_scale_int (vd->granulepos + sample_count,
- GST_SECOND, vd->vi.rate);
- GST_DEBUG_OBJECT (vd, "corresponding timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (timestamp));
- /* calculate a nano-second accurate duration */
- GST_BUFFER_DURATION (out) = GST_CLOCK_DIFF (timestamp, nextts);
- GST_DEBUG_OBJECT (vd, "set duration %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_DURATION (out)));
- } else {
- timestamp = -1;
- }
- }
- GST_BUFFER_TIMESTAMP (out) = timestamp;
-
- if (vd->granulepos != -1)
- vd->granulepos += sample_count;
-
- if (vd->segment.rate >= 0.0)
- result = vorbis_dec_push_forward (vd, out);
- else
- result = vorbis_dec_push_reverse (vd, out);
-
-done:
- vorbis_synthesis_read (&vd->vd, sample_count);
-
- GST_DEBUG_OBJECT (vd,
- "decoded %ld bytes into %d samples, ts %" GST_TIME_FORMAT, packet->bytes,
- sample_count, GST_TIME_ARGS (timestamp));
-
- /* granulepos is the last sample in the packet */
- if (packet->granulepos != -1)
- vd->granulepos = packet->granulepos;
-
- return result;
-
- /* ERRORS */
-not_initialized:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
- (NULL), ("no header sent yet"));
- return GST_FLOW_ERROR;
- }
-could_not_read:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
- (NULL), ("couldn't read data packet"));
- return GST_FLOW_ERROR;
- }
-not_accepted:
- {
- GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
- (NULL), ("vorbis decoder did not accept data packet"));
- return GST_FLOW_ERROR;
- }
-wrong_samples:
- {
- gst_buffer_unref (out);
- GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
- (NULL), ("vorbis decoder reported wrong number of samples"));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer)
-{
- ogg_packet packet;
- GstFlowReturn result = GST_FLOW_OK;
- GstClockTime timestamp;
- guint64 offset_end;
-
- timestamp = GST_BUFFER_TIMESTAMP (buffer);
- offset_end = GST_BUFFER_OFFSET_END (buffer);
-
- /* only ogg has granulepos, demuxers of other container formats
- * might provide us with timestamps instead (e.g. matroskademux) */
- if (offset_end == GST_BUFFER_OFFSET_NONE && timestamp != GST_CLOCK_TIME_NONE) {
- /* we might get multiple consecutive buffers with the same timestamp */
- if (timestamp != vd->prev_timestamp) {
- vd->cur_timestamp = timestamp;
- vd->prev_timestamp = timestamp;
- }
- } else {
- vd->cur_timestamp = GST_CLOCK_TIME_NONE;
- vd->prev_timestamp = GST_CLOCK_TIME_NONE;
- }
-
- /* make ogg_packet out of the buffer */
- packet.packet = GST_BUFFER_DATA (buffer);
- packet.bytes = GST_BUFFER_SIZE (buffer);
- packet.granulepos = offset_end;
- packet.packetno = 0; /* we don't care */
- /*
- * FIXME. Is there anyway to know that this is the last packet and
- * set e_o_s??
- * Yes there is, keep one packet at all times and only push out when
- * you receive a new one. Implement this.
- */
- packet.e_o_s = 0;
-
- /* error out on empty header packets, but just skip empty data packets */
- if (G_UNLIKELY (packet.bytes == 0)) {
- if (vd->initialized)
- goto empty_buffer;
- else
- goto empty_header;
- }
-
- GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GINT64_FORMAT,
- (gint64) packet.granulepos);
-
- /* switch depending on packet type */
- if (packet.packet[0] & 1) {
- if (vd->initialized) {
- GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet");
- goto done;
- }
- result = vorbis_handle_header_packet (vd, &packet);
- } else {
- result = vorbis_handle_data_packet (vd, &packet);
- }
-
-done:
- return result;
-
-empty_buffer:
- {
- /* don't error out here, just ignore the buffer, it's invalid for vorbis
- * but not fatal. */
- GST_WARNING_OBJECT (vd, "empty buffer received, ignoring");
- if (packet.granulepos != -1)
- vd->granulepos = packet.granulepos;
- result = GST_FLOW_OK;
- goto done;
- }
-
-/* ERRORS */
-empty_header:
- {
- GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty header received"));
- result = GST_FLOW_ERROR;
- vd->discont = TRUE;
- goto done;
- }
-}
-
-/*
- * Input:
- * Buffer decoding order: 7 8 9 4 5 6 3 1 2 EOS
- * Discont flag: D D D D
- *
- * - Each Discont marks a discont in the decoding order.
- *
- * for vorbis, each buffer is a keyframe when we have the previous
- * buffer. This means that to decode buffer 7, we need buffer 6, which
- * arrives out of order.
- *
- * we first gather buffers in the gather queue until we get a DISCONT. We
- * prepend each incomming buffer so that they are in reversed order.
- *
- * gather queue: 9 8 7
- * decode queue:
- * output queue:
- *
- * When a DISCONT is received (buffer 4), we move the gather queue to the
- * decode queue. This is simply done be taking the head of the gather queue
- * and prepending it to the decode queue. This yields:
- *
- * gather queue:
- * decode queue: 7 8 9
- * output queue:
- *
- * Then we decode each buffer in the decode queue in order and put the output
- * buffer in the output queue. The first buffer (7) will not produce and output
- * because it needs the previous buffer (6) which did not arrive yet. This
- * yields:
- *
- * gather queue:
- * decode queue: 7 8 9
- * output queue: 9 8
- *
- * Then we remove the consumed buffers from the decode queue. Buffer 7 is not
- * completely consumed, we need to keep it around for when we receive buffer
- * 6. This yields:
- *
- * gather queue:
- * decode queue: 7
- * output queue: 9 8
- *
- * Then we accumulate more buffers:
- *
- * gather queue: 6 5 4
- * decode queue: 7
- * output queue:
- *
- * prepending to the decode queue on DISCONT yields:
- *
- * gather queue:
- * decode queue: 4 5 6 7
- * output queue:
- *
- * after decoding and keeping buffer 4:
- *
- * gather queue:
- * decode queue: 4
- * output queue: 7 6 5
- *
- * Etc..
- */
-static GstFlowReturn
-vorbis_dec_flush_decode (GstVorbisDec * dec)
-{
- GstFlowReturn res = GST_FLOW_OK;
- GList *walk;
-
- walk = dec->decode;
-
- GST_DEBUG_OBJECT (dec, "flushing buffers to decoder");
-
- while (walk) {
- GList *next;
- GstBuffer *buf = GST_BUFFER_CAST (walk->data);
-
- GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
- buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
-
- next = g_list_next (walk);
-
- /* decode buffer, prepend to output queue */
- res = vorbis_dec_decode_buffer (dec, buf);
-
- /* if we generated output, we can discard the buffer, else we
- * keep it in the queue */
- if (dec->queued) {
- GST_DEBUG_OBJECT (dec, "decoded buffer to %p", dec->queued->data);
- dec->decode = g_list_delete_link (dec->decode, walk);
- gst_buffer_unref (buf);
- } else {
- GST_DEBUG_OBJECT (dec, "buffer did not decode, keeping");
- }
- walk = next;
- }
- if (dec->granulepos != -1) {
- GstClockTime endts;
-
- endts =
- gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
-
- GST_DEBUG_OBJECT (dec, "we have granulepos %" G_GUINT64_FORMAT ", ts %"
- GST_TIME_FORMAT, dec->granulepos, GST_TIME_ARGS (endts));
-
- while (dec->queued) {
- GstBuffer *buf;
- guint sample_count;
-
- buf = GST_BUFFER_CAST (dec->queued->data);
-
- sample_count =
- GST_BUFFER_SIZE (buf) / (dec->vi.channels * sizeof (float));
-
- GST_BUFFER_OFFSET_END (buf) = dec->granulepos;
- endts =
- gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
- dec->granulepos -= sample_count;
- GST_BUFFER_OFFSET (buf) = dec->granulepos;
- GST_BUFFER_TIMESTAMP (buf) =
- gst_util_uint64_scale_int (dec->granulepos, GST_SECOND, dec->vi.rate);
- GST_BUFFER_DURATION (buf) = endts - GST_BUFFER_TIMESTAMP (buf);
-
- /* clip, this will unref the buffer in case of clipping */
- if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate,
- dec->vi.channels * sizeof (float)))) {
- GST_DEBUG_OBJECT (dec, "clipped buffer %p", buf);
- goto next;
- }
-
- if (dec->discont) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
- dec->discont = FALSE;
- }
- GST_DEBUG_OBJECT (dec, "pushing buffer %p, samples %u, "
- "ts %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT,
- buf, sample_count, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
-
- res = gst_pad_push (dec->srcpad, buf);
- next:
- dec->queued = g_list_delete_link (dec->queued, dec->queued);
- }
- } else {
- GST_DEBUG_OBJECT (dec, "we don't have a granulepos yet, delayed push");
- }
- return res;
-}
-
-static GstFlowReturn
-vorbis_dec_chain_reverse (GstVorbisDec * vd, gboolean discont, GstBuffer * buf)
-{
- GstFlowReturn result = GST_FLOW_OK;
-
- /* if we have a discont, move buffers to the decode list */
- if (G_UNLIKELY (discont)) {
- GST_DEBUG_OBJECT (vd, "received discont");
- while (vd->gather) {
- GstBuffer *gbuf;
-
- gbuf = GST_BUFFER_CAST (vd->gather->data);
- /* remove from the gather list */
- vd->gather = g_list_delete_link (vd->gather, vd->gather);
- /* copy to decode queue */
- vd->decode = g_list_prepend (vd->decode, gbuf);
- }
- /* flush and decode the decode queue */
- result = vorbis_dec_flush_decode (vd);
- }
-
- GST_DEBUG_OBJECT (vd, "gathering buffer %p, size %u", buf,
- GST_BUFFER_SIZE (buf));
- /* add buffer to gather queue */
- vd->gather = g_list_prepend (vd->gather, buf);
-
- return result;
-}
-
-static GstFlowReturn
-vorbis_dec_chain_forward (GstVorbisDec * vd, gboolean discont,
- GstBuffer * buffer)
-{
- GstFlowReturn result;
-
- result = vorbis_dec_decode_buffer (vd, buffer);
-
- gst_buffer_unref (buffer);
-
- return result;
-
-}
-
-static GstFlowReturn
-vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstVorbisDec *vd;
- GstFlowReturn result = GST_FLOW_OK;
- gboolean discont;
-
- vd = GST_VORBIS_DEC (gst_pad_get_parent (pad));
-
- discont = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT);
-
- /* resync on DISCONT */
- if (G_UNLIKELY (discont)) {
- GST_DEBUG_OBJECT (vd, "received DISCONT buffer");
- vd->granulepos = -1;
- vd->cur_timestamp = GST_CLOCK_TIME_NONE;
- vd->prev_timestamp = GST_CLOCK_TIME_NONE;
-#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
- vorbis_synthesis_restart (&vd->vd);
-#endif
- vd->discont = TRUE;
- }
-
- if (vd->segment.rate >= 0.0)
- result = vorbis_dec_chain_forward (vd, discont, buffer);
- else
- result = vorbis_dec_chain_reverse (vd, discont, buffer);
-
- gst_object_unref (vd);
-
- return result;
-}
-
-static GstStateChangeReturn
-vorbis_dec_change_state (GstElement * element, GstStateChange transition)
-{
- GstVorbisDec *vd = GST_VORBIS_DEC (element);
- GstStateChangeReturn res;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- vorbis_info_init (&vd->vi);
- vorbis_comment_init (&vd->vc);
- vd->initialized = FALSE;
- gst_vorbis_dec_reset (vd);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- res = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_DEBUG_OBJECT (vd, "PAUSED -> READY, clearing vorbis structures");
- vorbis_block_clear (&vd->vb);
- vorbis_dsp_clear (&vd->vd);
- vorbis_comment_clear (&vd->vc);
- vorbis_info_clear (&vd->vi);
- gst_vorbis_dec_reset (vd);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return res;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisdec.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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 __GST_VORBIS_DEC_H__
-#define __GST_VORBIS_DEC_H__
-
-
-#include <gst/gst.h>
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBIS_DEC \
- (gst_vorbis_dec_get_type())
-#define GST_VORBIS_DEC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_DEC,GstVorbisDec))
-#define GST_VORBIS_DEC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_DEC,GstVorbisDecClass))
-#define GST_IS_VORBIS_DEC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_DEC))
-#define GST_IS_VORBIS_DEC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_DEC))
-
-typedef struct _GstVorbisDec GstVorbisDec;
-typedef struct _GstVorbisDecClass GstVorbisDecClass;
-
-/**
- * GstVorbisDec:
- *
- * Opaque data structure.
- */
-struct _GstVorbisDec {
- GstElement element;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- vorbis_dsp_state vd;
- vorbis_info vi;
- vorbis_comment vc;
- vorbis_block vb;
- guint64 granulepos;
-
- gboolean initialized;
-
- /* list of buffers that need timestamps */
- GList *queued;
- /* list of raw output buffers */
- GList *output;
- /* gather/decode queues for reverse playback */
- GList *gather;
- GList *decode;
-
- GstSegment segment;
- gboolean discont;
-
- GstClockTime cur_timestamp; /* only used with non-ogg container formats */
- GstClockTime prev_timestamp; /* only used with non-ogg container formats */
-
- GList *pendingevents;
- GstTagList *taglist;
-};
-
-struct _GstVorbisDecClass {
- GstElementClass parent_class;
-};
-
-GType gst_vorbis_dec_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_DEC_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbisenc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1389 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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.
- */
-
-/**
- * SECTION:element-vorbisenc
- * @short_description: an encoder that encodes audio to Vorbis
- * @see_also: vorbisdec, oggmux
- *
- * <refsect2>
- * <para>
- * This element encodes raw float audio into a Vorbis stream.
- * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
- * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
- * Foundation</ulink>.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * Encode a test sine signal to Ogg/Vorbis. Note that the resulting file
- * will be really small because a sine signal compresses very well.
- * </para>
- * <programlisting>
- * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg
- * </programlisting>
- * <para>
- * Record from a sound card using ALSA and encode to Ogg/Vorbis.
- * </para>
- * <programlisting>
- * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2006-03-01 (0.10.4)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <vorbis/vorbisenc.h>
-
-#include <gst/gsttagsetter.h>
-#include <gst/tag/tag.h>
-#include <gst/audio/multichannel.h>
-#include "vorbisenc.h"
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug);
-#define GST_CAT_DEFAULT vorbisenc_debug
-
-static GstPadTemplate *gst_vorbis_enc_src_template,
- *gst_vorbis_enc_sink_template;
-
-/* elementfactory information */
-static const GstElementDetails vorbisenc_details =
-GST_ELEMENT_DETAILS ("Vorbis audio encoder",
- "Codec/Encoder/Audio",
- "Encodes audio in Vorbis format",
- "Monty <monty@xiph.org>, " "Wim Taymans <wim@fluendo.com>");
-
-enum
-{
- ARG_0,
- ARG_MAX_BITRATE,
- ARG_BITRATE,
- ARG_MIN_BITRATE,
- ARG_QUALITY,
- ARG_MANAGED,
- ARG_LAST_MESSAGE
-};
-
-static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc);
-
-/* this function takes into account the granulepos_offset and the subgranule
- * time offset */
-static GstClockTime
-granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc,
- ogg_int64_t granulepos)
-{
- if (granulepos >= 0)
- return gst_util_uint64_scale ((guint64) granulepos
- + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency)
- + vorbisenc->subgranule_offset;
- return GST_CLOCK_TIME_NONE;
-}
-
-/* this function does a straight granulepos -> timestamp conversion */
-static GstClockTime
-granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos)
-{
- if (granulepos >= 0)
- return gst_util_uint64_scale ((guint64) granulepos,
- GST_SECOND, vorbisenc->frequency);
- return GST_CLOCK_TIME_NONE;
-}
-
-#define MAX_BITRATE_DEFAULT -1
-#define BITRATE_DEFAULT -1
-#define MIN_BITRATE_DEFAULT -1
-#define QUALITY_DEFAULT 0.3
-#define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */
-#define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */
-
-static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event);
-static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc);
-
-static void gst_vorbis_enc_dispose (GObject * object);
-static void gst_vorbis_enc_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-static void gst_vorbis_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element,
- GstStateChange transition);
-static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type);
-
-GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement,
- GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces);
-
-static void
-gst_vorbis_enc_add_interfaces (GType vorbisenc_type)
-{
- static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
-
- g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER,
- &tag_setter_info);
-}
-
-static GstCaps *
-vorbis_caps_factory (void)
-{
- return gst_caps_new_simple ("audio/x-vorbis", NULL);
-}
-
-static GstCaps *
-raw_caps_factory (void)
-{
- /* lowest, highest sample rates come from vorbis/lib/modes/setup_X.h:
- * 1-200000 Hz */
- return
- gst_caps_new_simple ("audio/x-raw-float",
- "rate", GST_TYPE_INT_RANGE, 1, 200000,
- "channels", GST_TYPE_INT_RANGE, 1, 256,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
-}
-
-static void
-gst_vorbis_enc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- GstCaps *raw_caps, *vorbis_caps;
-
- raw_caps = raw_caps_factory ();
- vorbis_caps = vorbis_caps_factory ();
-
- gst_vorbis_enc_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
- GST_PAD_ALWAYS, raw_caps);
- gst_vorbis_enc_src_template = gst_pad_template_new ("src", GST_PAD_SRC,
- GST_PAD_ALWAYS, vorbis_caps);
- gst_element_class_add_pad_template (element_class,
- gst_vorbis_enc_sink_template);
- gst_element_class_add_pad_template (element_class,
- gst_vorbis_enc_src_template);
- gst_element_class_set_details (element_class, &vorbisenc_details);
-}
-
-static void
-gst_vorbis_enc_class_init (GstVorbisEncClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- gobject_class->set_property = gst_vorbis_enc_set_property;
- gobject_class->get_property = gst_vorbis_enc_get_property;
- gobject_class->dispose = gst_vorbis_enc_dispose;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE,
- g_param_spec_int ("max-bitrate", "Maximum Bitrate",
- "Specify a maximum bitrate (in bps). Useful for streaming "
- "applications. (-1 == disabled)",
- -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
- g_param_spec_int ("bitrate", "Target Bitrate",
- "Attempt to encode at a bitrate averaging this (in bps). "
- "This uses the bitrate management engine, and is not recommended for most users. "
- "Quality is a better alternative. (-1 == disabled)",
- -1, HIGHEST_BITRATE, BITRATE_DEFAULT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE,
- g_param_spec_int ("min_bitrate", "Minimum Bitrate",
- "Specify a minimum bitrate (in bps). Useful for encoding for a "
- "fixed-size channel. (-1 == disabled)",
- -1, HIGHEST_BITRATE, MIN_BITRATE_DEFAULT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
- g_param_spec_float ("quality", "Quality",
- "Specify quality instead of specifying a particular bitrate.",
- -0.1, 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED,
- g_param_spec_boolean ("managed", "Managed",
- "Enable bitrate management engine", FALSE, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE,
- g_param_spec_string ("last-message", "last-message",
- "The last status message", NULL, G_PARAM_READABLE));
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state);
-}
-
-static void
-gst_vorbis_enc_dispose (GObject * object)
-{
- GstVorbisEnc *vorbisenc = GST_VORBISENC (object);
-
- if (vorbisenc->sinkcaps) {
- gst_caps_unref (vorbisenc->sinkcaps);
- vorbisenc->sinkcaps = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static const GstAudioChannelPosition vorbischannelpositions[][6] = {
- { /* Mono */
- GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
- { /* Stereo */
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
- { /* Stereo + Centre */
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
- { /* Quadraphonic */
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- },
- { /* Stereo + Centre + rear stereo */
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- },
- { /* Full 5.1 Surround */
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_LFE,
- },
-};
-static GstCaps *
-gst_vorbis_enc_generate_sink_caps (void)
-{
- GstCaps *caps = gst_caps_new_empty ();
- int i, c;
-
- gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
- "rate", GST_TYPE_INT_RANGE, 1, 200000,
- "channels", G_TYPE_INT, 1,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
- NULL));
-
- gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
- "rate", GST_TYPE_INT_RANGE, 1, 200000,
- "channels", G_TYPE_INT, 2,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
- NULL));
-
- for (i = 3; i <= 6; i++) {
- GValue chanpos = { 0 };
- GValue pos = { 0 };
- GstStructure *structure;
-
- g_value_init (&chanpos, GST_TYPE_ARRAY);
- g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION);
-
- for (c = 0; c < i; c++) {
- g_value_set_enum (&pos, vorbischannelpositions[i - 1][c]);
- gst_value_array_append_value (&chanpos, &pos);
- }
- g_value_unset (&pos);
-
- structure = gst_structure_new ("audio/x-raw-float",
- "rate", GST_TYPE_INT_RANGE, 1, 200000,
- "channels", G_TYPE_INT, i,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL);
- gst_structure_set_value (structure, "channel-positions", &chanpos);
- g_value_unset (&chanpos);
-
- gst_caps_append_structure (caps, structure);
- }
-
- gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float",
- "rate", GST_TYPE_INT_RANGE, 1, 200000,
- "channels", GST_TYPE_INT_RANGE, 7, 256,
- "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
- NULL));
-
- return caps;
-}
-
-static GstCaps *
-gst_vorbis_enc_sink_getcaps (GstPad * pad)
-{
- GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
- if (vorbisenc->sinkcaps == NULL)
- vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps ();
-
- return gst_caps_ref (vorbisenc->sinkcaps);
-}
-
-static gboolean
-gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
-{
- GstVorbisEnc *vorbisenc;
- GstStructure *structure;
-
- vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
- vorbisenc->setup = FALSE;
-
- structure = gst_caps_get_structure (caps, 0);
- gst_structure_get_int (structure, "channels", &vorbisenc->channels);
- gst_structure_get_int (structure, "rate", &vorbisenc->frequency);
-
- gst_vorbis_enc_setup (vorbisenc);
-
- if (vorbisenc->setup)
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
-gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstVorbisEnc *vorbisenc;
- gint64 avg;
-
- vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
-
- if (vorbisenc->samples_in == 0 ||
- vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) {
- gst_object_unref (vorbisenc);
- return FALSE;
- }
-
- avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in);
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_TIME:
- *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
- gst_object_unref (vorbisenc);
- return res;
-}
-
-static gboolean
-gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format,
- gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- guint scale = 1;
- gint bytes_per_sample;
- GstVorbisEnc *vorbisenc;
-
- vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
-
- bytes_per_sample = vorbisenc->channels * 2;
-
- switch (src_format) {
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- if (bytes_per_sample == 0)
- return FALSE;
- *dest_value = src_value / bytes_per_sample;
- break;
- case GST_FORMAT_TIME:
- {
- gint byterate = bytes_per_sample * vorbisenc->frequency;
-
- if (byterate == 0)
- return FALSE;
- *dest_value =
- gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
- break;
- }
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * bytes_per_sample;
- break;
- case GST_FORMAT_TIME:
- if (vorbisenc->frequency == 0)
- return FALSE;
- *dest_value =
- gst_util_uint64_scale_int (src_value, GST_SECOND,
- vorbisenc->frequency);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- scale = bytes_per_sample;
- /* fallthrough */
- case GST_FORMAT_DEFAULT:
- *dest_value =
- gst_util_uint64_scale_int (src_value,
- scale * vorbisenc->frequency, GST_SECOND);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
- gst_object_unref (vorbisenc);
- return res;
-}
-
-static const GstQueryType *
-gst_vorbis_enc_get_query_types (GstPad * pad)
-{
- static const GstQueryType gst_vorbis_enc_src_query_types[] = {
- GST_QUERY_POSITION,
- GST_QUERY_DURATION,
- GST_QUERY_CONVERT,
- 0
- };
-
- return gst_vorbis_enc_src_query_types;
-}
-
-static gboolean
-gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query)
-{
- gboolean res = TRUE;
- GstVorbisEnc *vorbisenc;
- GstPad *peerpad;
-
- vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad));
- peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- GstFormat fmt, req_fmt;
- gint64 pos, val;
-
- gst_query_parse_position (query, &req_fmt, NULL);
- if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) {
- gst_query_set_position (query, req_fmt, val);
- break;
- }
-
- fmt = GST_FORMAT_TIME;
- if (!(res = gst_pad_query_position (peerpad, &fmt, &pos)))
- break;
-
- if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) {
- gst_query_set_position (query, req_fmt, val);
- }
- break;
- }
- case GST_QUERY_DURATION:
- {
- GstFormat fmt, req_fmt;
- gint64 dur, val;
-
- gst_query_parse_duration (query, &req_fmt, NULL);
- if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) {
- gst_query_set_duration (query, req_fmt, val);
- break;
- }
-
- fmt = GST_FORMAT_TIME;
- if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur)))
- break;
-
- if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) {
- gst_query_set_duration (query, req_fmt, val);
- }
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
-error:
- gst_object_unref (peerpad);
- gst_object_unref (vorbisenc);
- return res;
-}
-
-static gboolean
-gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query)
-{
- gboolean res = TRUE;
- GstVorbisEnc *vorbisenc;
-
- vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
-error:
- return res;
-}
-
-static void
-gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass)
-{
- vorbisenc->sinkpad =
- gst_pad_new_from_template (gst_vorbis_enc_sink_template, "sink");
- gst_pad_set_event_function (vorbisenc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event));
- gst_pad_set_chain_function (vorbisenc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain));
- gst_pad_set_setcaps_function (vorbisenc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps));
- gst_pad_set_getcaps_function (vorbisenc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps));
- gst_pad_set_query_function (vorbisenc->sinkpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query));
- gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad);
-
- vorbisenc->srcpad =
- gst_pad_new_from_template (gst_vorbis_enc_src_template, "src");
- gst_pad_set_query_function (vorbisenc->srcpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query));
- gst_pad_set_query_type_function (vorbisenc->srcpad,
- GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types));
- gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad);
-
- vorbisenc->channels = -1;
- vorbisenc->frequency = -1;
-
- vorbisenc->managed = FALSE;
- vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT;
- vorbisenc->bitrate = BITRATE_DEFAULT;
- vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT;
- vorbisenc->quality = QUALITY_DEFAULT;
- vorbisenc->quality_set = FALSE;
- vorbisenc->last_message = NULL;
-}
-
-static void
-gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag,
- gpointer vorbisenc)
-{
- GstVorbisEnc *enc = GST_VORBISENC (vorbisenc);
- GList *vc_list, *l;
-
- vc_list = gst_tag_to_vorbis_comments (list, tag);
-
- for (l = vc_list; l != NULL; l = l->next) {
- const gchar *vc_string = (const gchar *) l->data;
- gchar *key = NULL, *val = NULL;
-
- GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string);
- if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) {
- vorbis_comment_add_tag (&enc->vc, key, val);
- g_free (key);
- g_free (val);
- }
- }
-
- g_list_foreach (vc_list, (GFunc) g_free, NULL);
- g_list_free (vc_list);
-}
-
-static void
-gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
-{
- GstTagList *merged_tags;
- const GstTagList *user_tags;
-
- vorbis_comment_init (&enc->vc);
-
- user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));
-
- GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
- GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);
-
- /* gst_tag_list_merge() will handle NULL for either or both lists fine */
- merged_tags = gst_tag_list_merge (user_tags, enc->tags,
- gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
-
- if (merged_tags) {
- GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags);
- gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
- gst_tag_list_free (merged_tags);
- }
-}
-
-static gchar *
-get_constraints_string (GstVorbisEnc * vorbisenc)
-{
- gint min = vorbisenc->min_bitrate;
- gint max = vorbisenc->max_bitrate;
- gchar *result;
-
- if (min > 0 && max > 0)
- result = g_strdup_printf ("(min %d bps, max %d bps)", min, max);
- else if (min > 0)
- result = g_strdup_printf ("(min %d bps, no max)", min);
- else if (max > 0)
- result = g_strdup_printf ("(no min, max %d bps)", max);
- else
- result = g_strdup_printf ("(no min or max)");
-
- return result;
-}
-
-static void
-update_start_message (GstVorbisEnc * vorbisenc)
-{
- gchar *constraints;
-
- g_free (vorbisenc->last_message);
-
- if (vorbisenc->bitrate > 0) {
- if (vorbisenc->managed) {
- constraints = get_constraints_string (vorbisenc);
- vorbisenc->last_message =
- g_strdup_printf ("encoding at average bitrate %d bps %s",
- vorbisenc->bitrate, constraints);
- g_free (constraints);
- } else {
- vorbisenc->last_message =
- g_strdup_printf
- ("encoding at approximate bitrate %d bps (VBR encoding enabled)",
- vorbisenc->bitrate);
- }
- } else {
- if (vorbisenc->quality_set) {
- if (vorbisenc->managed) {
- constraints = get_constraints_string (vorbisenc);
- vorbisenc->last_message =
- g_strdup_printf
- ("encoding at quality level %2.2f using constrained VBR %s",
- vorbisenc->quality, constraints);
- g_free (constraints);
- } else {
- vorbisenc->last_message =
- g_strdup_printf ("encoding at quality level %2.2f",
- vorbisenc->quality);
- }
- } else {
- constraints = get_constraints_string (vorbisenc);
- vorbisenc->last_message =
- g_strdup_printf ("encoding using bitrate management %s", constraints);
- g_free (constraints);
- }
- }
-
- g_object_notify (G_OBJECT (vorbisenc), "last_message");
-}
-
-static gboolean
-gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
-{
- vorbisenc->setup = FALSE;
-
- if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
- && vorbisenc->max_bitrate < 0) {
- vorbisenc->quality_set = TRUE;
- }
-
- update_start_message (vorbisenc);
-
- /* choose an encoding mode */
- /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
- vorbis_info_init (&vorbisenc->vi);
-
- if (vorbisenc->quality_set) {
- if (vorbis_encode_setup_vbr (&vorbisenc->vi,
- vorbisenc->channels, vorbisenc->frequency,
- vorbisenc->quality) != 0) {
- GST_ERROR_OBJECT (vorbisenc,
- "vorbisenc: initialisation failed: invalid parameters for quality");
- vorbis_info_clear (&vorbisenc->vi);
- return FALSE;
- }
-
- /* do we have optional hard quality restrictions? */
- if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
- struct ovectl_ratemanage_arg ai;
-
- vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);
-
- ai.bitrate_hard_min = vorbisenc->min_bitrate;
- ai.bitrate_hard_max = vorbisenc->max_bitrate;
- ai.management_active = 1;
-
- vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
- }
- } else {
- long min_bitrate, max_bitrate;
-
- min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
- max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;
-
- if (vorbis_encode_setup_managed (&vorbisenc->vi,
- vorbisenc->channels,
- vorbisenc->frequency,
- max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
- GST_ERROR_OBJECT (vorbisenc,
- "vorbis_encode_setup_managed "
- "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
- vorbisenc->channels, vorbisenc->frequency, max_bitrate,
- vorbisenc->bitrate, min_bitrate);
- vorbis_info_clear (&vorbisenc->vi);
- return FALSE;
- }
- }
-
- if (vorbisenc->managed && vorbisenc->bitrate < 0) {
- vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
- } else if (!vorbisenc->managed) {
- /* Turn off management entirely (if it was turned on). */
- vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
- }
- vorbis_encode_setup_init (&vorbisenc->vi);
-
- /* set up the analysis state and auxiliary encoding storage */
- vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi);
- vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb);
-
- vorbisenc->next_ts = 0;
-
- vorbisenc->setup = TRUE;
-
- return TRUE;
-}
-
-static GstFlowReturn
-gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- if (vorbisenc->setup) {
- vorbis_analysis_wrote (&vorbisenc->vd, 0);
- ret = gst_vorbis_enc_output_buffers (vorbisenc);
-
- vorbisenc->setup = FALSE;
- }
-
- /* clean up and exit. vorbis_info_clear() must be called last */
- vorbis_block_clear (&vorbisenc->vb);
- vorbis_dsp_clear (&vorbisenc->vd);
- vorbis_info_clear (&vorbisenc->vi);
-
- vorbisenc->header_sent = FALSE;
-
- return ret;
-}
-
-/* prepare a buffer for transmission by passing data through libvorbis */
-static GstBuffer *
-gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc,
- ogg_packet * packet)
-{
- GstBuffer *outbuf;
-
- outbuf = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
- /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its
- * time representation */
- GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos +
- vorbisenc->granulepos_offset;
- GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc,
- GST_BUFFER_OFFSET_END (outbuf));
- GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts;
-
- /* update the next timestamp, taking granulepos_offset and subgranule offset
- * into account */
- vorbisenc->next_ts =
- granulepos_to_timestamp_offset (vorbisenc, packet->granulepos);
- GST_BUFFER_DURATION (outbuf) =
- vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
-
- if (vorbisenc->next_discont) {
- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- vorbisenc->next_discont = FALSE;
- }
-
- GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes",
- GST_BUFFER_SIZE (outbuf));
- return outbuf;
-}
-
-/* the same as above, but different logic for setting timestamp and granulepos
- * */
-static GstBuffer *
-gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc,
- ogg_packet * packet)
-{
- GstBuffer *outbuf;
-
- outbuf = gst_buffer_new_and_alloc (packet->bytes);
- memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
- GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
- GST_BUFFER_OFFSET_END (outbuf) = 0;
- GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
- GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
-
- gst_buffer_set_caps (outbuf, vorbisenc->srccaps);
-
- GST_DEBUG ("created header packet buffer, %d bytes",
- GST_BUFFER_SIZE (outbuf));
- return outbuf;
-}
-
-/* push out the buffer and do internal bookkeeping */
-static GstFlowReturn
-gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer)
-{
- vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer);
-
- GST_DEBUG_OBJECT (vorbisenc, "Pushing buffer with GP %lld, ts %lld",
- GST_BUFFER_OFFSET_END (buffer), GST_BUFFER_TIMESTAMP (buffer));
- return gst_pad_push (vorbisenc->srcpad, buffer);
-}
-
-static GstFlowReturn
-gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet)
-{
- GstBuffer *outbuf;
-
- outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet);
- return gst_vorbis_enc_push_buffer (vorbisenc, outbuf);
-}
-
-/* Set a copy of these buffers as 'streamheader' on the caps.
- * We need a copy to avoid these buffers ending up with (indirect) refs on
- * themselves
- */
-static GstCaps *
-gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1,
- GstBuffer * buf2, GstBuffer * buf3)
-{
- GstBuffer *buf;
- GstStructure *structure;
- GValue array = { 0 };
- GValue value = { 0 };
-
- caps = gst_caps_make_writable (caps);
- structure = gst_caps_get_structure (caps, 0);
-
- /* mark buffers */
- GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
- /* put buffers in a fixed list */
- g_value_init (&array, GST_TYPE_ARRAY);
- g_value_init (&value, GST_TYPE_BUFFER);
- buf = gst_buffer_copy (buf1);
- gst_value_set_buffer (&value, buf);
- gst_buffer_unref (buf);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- g_value_init (&value, GST_TYPE_BUFFER);
- buf = gst_buffer_copy (buf2);
- gst_value_set_buffer (&value, buf);
- gst_buffer_unref (buf);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- g_value_init (&value, GST_TYPE_BUFFER);
- buf = gst_buffer_copy (buf3);
- gst_value_set_buffer (&value, buf);
- gst_buffer_unref (buf);
- gst_value_array_append_value (&array, &value);
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&value);
- g_value_unset (&array);
-
- return caps;
-}
-
-static gboolean
-gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean res = TRUE;
- GstVorbisEnc *vorbisenc;
-
- vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- /* Tell the library we're at end of stream so that it can handle
- * the last frame and mark end of stream in the output properly */
- GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on");
- gst_vorbis_enc_clear (vorbisenc);
-
- res = gst_pad_push_event (vorbisenc->srcpad, event);
- break;
- case GST_EVENT_TAG:
- if (vorbisenc->tags) {
- GstTagList *list;
-
- gst_event_parse_tag (event, &list);
- gst_tag_list_insert (vorbisenc->tags, list,
- gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc)));
- } else {
- g_assert_not_reached ();
- }
- res = gst_pad_push_event (vorbisenc->srcpad, event);
- break;
- default:
- res = gst_pad_push_event (vorbisenc->srcpad, event);
- break;
- }
- return res;
-}
-
-static gboolean
-gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
- GstBuffer * buffer)
-{
- gboolean ret = FALSE;
-
- if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
- vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
- GST_BUFFER_TIMESTAMP (buffer) != vorbisenc->expected_ts) {
- /* It turns out that a lot of elements don't generate perfect streams due
- * to rounding errors. So, we permit small errors (< 1/2 a sample) without
- * causing a discont.
- */
- int halfsample = GST_SECOND / vorbisenc->frequency / 2;
-
- if ((GstClockTimeDiff) (GST_BUFFER_TIMESTAMP (buffer) -
- vorbisenc->expected_ts) > halfsample) {
- GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
- ", buffer TS %" GST_TIME_FORMAT,
- GST_TIME_ARGS (vorbisenc->expected_ts),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- ret = TRUE;
- }
- }
-
- if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
- GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE) {
- vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer) +
- GST_BUFFER_DURATION (buffer);
- } else
- vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
-
- return ret;
-}
-
-static GstFlowReturn
-gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstVorbisEnc *vorbisenc;
- GstFlowReturn ret = GST_FLOW_OK;
- gfloat *data;
- gulong size;
- gulong i, j;
- float **vorbis_buffer;
- GstBuffer *buf1, *buf2, *buf3;
- gboolean first = FALSE;
-
- vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
-
- if (!vorbisenc->setup)
- goto not_setup;
-
- if (!vorbisenc->header_sent) {
- /* Vorbis streams begin with three headers; the initial header (with
- most of the codec setup parameters) which is mandated by the Ogg
- bitstream spec. The second header holds any comment fields. The
- third header holds the bitstream codebook. We merely need to
- make the headers, then pass them to libvorbis one at a time;
- libvorbis handles the additional Ogg bitstream constraints */
- ogg_packet header;
- ogg_packet header_comm;
- ogg_packet header_code;
- GstCaps *caps;
-
- /* first, make sure header buffers get timestamp == 0 */
- vorbisenc->next_ts = 0;
- vorbisenc->granulepos_offset = 0;
- vorbisenc->subgranule_offset = 0;
-
- GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets");
- gst_vorbis_enc_set_metadata (vorbisenc);
- vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header,
- &header_comm, &header_code);
- vorbis_comment_clear (&vorbisenc->vc);
-
- /* create header buffers */
- buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header);
- buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm);
- buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code);
-
- /* mark and put on caps */
- vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL);
- caps = vorbisenc->srccaps;
- caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3);
-
- /* negotiate with these caps */
- GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
- gst_pad_set_caps (vorbisenc->srcpad, caps);
-
- gst_buffer_set_caps (buf1, caps);
- gst_buffer_set_caps (buf2, caps);
- gst_buffer_set_caps (buf3, caps);
-
- /* push out buffers */
- /* push_buffer takes the reference even for failure */
- if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK)
- goto failed_header_push;
- if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) {
- buf2 = NULL;
- goto failed_header_push;
- }
- if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) {
- buf3 = NULL;
- goto failed_header_push;
- }
-
- /* now adjust starting granulepos accordingly if the buffer's timestamp is
- nonzero */
- vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
- vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer);
- vorbisenc->granulepos_offset = gst_util_uint64_scale
- (GST_BUFFER_TIMESTAMP (buffer), vorbisenc->frequency, GST_SECOND);
- vorbisenc->subgranule_offset = 0;
- vorbisenc->subgranule_offset =
- vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
-
- vorbisenc->header_sent = TRUE;
- first = TRUE;
- }
-
- if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
- GST_BUFFER_TIMESTAMP (buffer) < vorbisenc->expected_ts) {
- GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
- "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
- "), cannot handle. Dropping buffer.",
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (vorbisenc->expected_ts));
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-
- if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, buffer) && !first) {
- GST_WARNING_OBJECT (vorbisenc, "Buffer is discontinuous, flushing encoder "
- "and restarting (Discont from %" GST_TIME_FORMAT
- " to %" GST_TIME_FORMAT ")", GST_TIME_ARGS (vorbisenc->next_ts),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- /* Re-initialise encoder (there's unfortunately no API to flush it) */
- if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
- return ret;
- if (!gst_vorbis_enc_setup (vorbisenc))
- return GST_FLOW_ERROR; /* Should be impossible, we can only get here if
- we successfully initialised earlier */
-
- /* Now, set our granulepos offset appropriately. */
- vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
- /* We need to round to the nearest whole number of samples, not just do
- * a truncating division here */
- vorbisenc->granulepos_offset = gst_util_uint64_scale
- (GST_BUFFER_TIMESTAMP (buffer) + GST_SECOND / vorbisenc->frequency / 2
- - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
-
- vorbisenc->header_sent = TRUE;
-
- /* And our next output buffer must have DISCONT set on it */
- vorbisenc->next_discont = TRUE;
- }
-
- /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */
- if (GST_BUFFER_SIZE (buffer) == 0) {
- gst_buffer_unref (buffer);
- return GST_FLOW_OK;
- }
-
- /* data to encode */
- data = (gfloat *) GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float));
-
- /* expose the buffer to submit data */
- vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size);
-
- /* deinterleave samples, write the buffer data */
- for (i = 0; i < size; i++) {
- for (j = 0; j < vorbisenc->channels; j++) {
- vorbis_buffer[j][i] = *data++;
- }
- }
-
- /* tell the library how much we actually submitted */
- vorbis_analysis_wrote (&vorbisenc->vd, size);
-
- vorbisenc->samples_in += size;
-
- gst_buffer_unref (buffer);
-
- ret = gst_vorbis_enc_output_buffers (vorbisenc);
-
- return ret;
-
- /* error cases */
-not_setup:
- {
- gst_buffer_unref (buffer);
- GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL),
- ("encoder not initialized (input is not audio?)"));
- return GST_FLOW_UNEXPECTED;
- }
-failed_header_push:
- {
- GST_WARNING_OBJECT (vorbisenc, "Failed to push headers");
- /* buf1 is always already unreffed */
- if (buf2)
- gst_buffer_unref (buf2);
- if (buf3)
- gst_buffer_unref (buf3);
- gst_buffer_unref (buffer);
- return ret;
- }
-}
-
-static GstFlowReturn
-gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc)
-{
- GstFlowReturn ret;
-
- /* vorbis does some data preanalysis, then divides up blocks for
- more involved (potentially parallel) processing. Get a single
- block for encoding now */
- while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) {
- ogg_packet op;
-
- GST_LOG_OBJECT (vorbisenc, "analysed to a block");
-
- /* analysis */
- vorbis_analysis (&vorbisenc->vb, NULL);
- vorbis_bitrate_addblock (&vorbisenc->vb);
-
- while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) {
- GST_LOG_OBJECT (vorbisenc, "pushing out a data packet");
- ret = gst_vorbis_enc_push_packet (vorbisenc, &op);
-
- if (ret != GST_FLOW_OK)
- return ret;
- }
- }
-
- return GST_FLOW_OK;
-}
-
-static void
-gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstVorbisEnc *vorbisenc;
-
- g_return_if_fail (GST_IS_VORBISENC (object));
-
- vorbisenc = GST_VORBISENC (object);
-
- switch (prop_id) {
- case ARG_MAX_BITRATE:
- g_value_set_int (value, vorbisenc->max_bitrate);
- break;
- case ARG_BITRATE:
- g_value_set_int (value, vorbisenc->bitrate);
- break;
- case ARG_MIN_BITRATE:
- g_value_set_int (value, vorbisenc->min_bitrate);
- break;
- case ARG_QUALITY:
- g_value_set_float (value, vorbisenc->quality);
- break;
- case ARG_MANAGED:
- g_value_set_boolean (value, vorbisenc->managed);
- break;
- case ARG_LAST_MESSAGE:
- g_value_set_string (value, vorbisenc->last_message);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_vorbis_enc_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstVorbisEnc *vorbisenc;
-
- g_return_if_fail (GST_IS_VORBISENC (object));
-
- vorbisenc = GST_VORBISENC (object);
-
- switch (prop_id) {
- case ARG_MAX_BITRATE:
- {
- gboolean old_value = vorbisenc->managed;
-
- vorbisenc->max_bitrate = g_value_get_int (value);
- if (vorbisenc->max_bitrate >= 0
- && vorbisenc->max_bitrate < LOWEST_BITRATE) {
- g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
- vorbisenc->max_bitrate = LOWEST_BITRATE;
- }
- if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
- vorbisenc->managed = TRUE;
- else
- vorbisenc->managed = FALSE;
-
- if (old_value != vorbisenc->managed)
- g_object_notify (object, "managed");
- break;
- }
- case ARG_BITRATE:
- vorbisenc->bitrate = g_value_get_int (value);
- if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) {
- g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
- vorbisenc->bitrate = LOWEST_BITRATE;
- }
- break;
- case ARG_MIN_BITRATE:
- {
- gboolean old_value = vorbisenc->managed;
-
- vorbisenc->min_bitrate = g_value_get_int (value);
- if (vorbisenc->min_bitrate >= 0
- && vorbisenc->min_bitrate < LOWEST_BITRATE) {
- g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE);
- vorbisenc->min_bitrate = LOWEST_BITRATE;
- }
- if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0)
- vorbisenc->managed = TRUE;
- else
- vorbisenc->managed = FALSE;
-
- if (old_value != vorbisenc->managed)
- g_object_notify (object, "managed");
- break;
- }
- case ARG_QUALITY:
- vorbisenc->quality = g_value_get_float (value);
- if (vorbisenc->quality >= 0.0)
- vorbisenc->quality_set = TRUE;
- else
- vorbisenc->quality_set = FALSE;
- break;
- case ARG_MANAGED:
- vorbisenc->managed = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static GstStateChangeReturn
-gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
-{
- GstVorbisEnc *vorbisenc = GST_VORBISENC (element);
- GstStateChangeReturn res;
-
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- vorbisenc->tags = gst_tag_list_new ();
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- vorbisenc->setup = FALSE;
- vorbisenc->next_discont = FALSE;
- vorbisenc->header_sent = FALSE;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- vorbis_block_clear (&vorbisenc->vb);
- vorbis_dsp_clear (&vorbisenc->vd);
- vorbis_info_clear (&vorbisenc->vi);
- g_free (vorbisenc->last_message);
- vorbisenc->last_message = NULL;
- if (vorbisenc->srccaps) {
- gst_caps_unref (vorbisenc->srccaps);
- vorbisenc->srccaps = NULL;
- }
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_tag_list_free (vorbisenc->tags);
- vorbisenc->tags = NULL;
- default:
- break;
- }
-
- return res;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisenc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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 __GST_VORBIS_ENC_H__
-#define __GST_VORBIS_ENC_H__
-
-
-#include <gst/gst.h>
-
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBISENC \
- (gst_vorbis_enc_get_type())
-#define GST_VORBISENC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBISENC,GstVorbisEnc))
-#define GST_VORBISENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBISENC,GstVorbisEncClass))
-#define GST_IS_VORBISENC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBISENC))
-#define GST_IS_VORBISENC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBISENC))
-
-typedef struct _GstVorbisEnc GstVorbisEnc;
-typedef struct _GstVorbisEncClass GstVorbisEncClass;
-
-/**
- * GstVorbisEnc:
- *
- * Opaque data structure.
- */
-struct _GstVorbisEnc {
- GstElement element;
-
- GstPad *sinkpad;
- GstPad *srcpad;
-
- GstCaps *srccaps;
- GstCaps *sinkcaps;
-
- vorbis_info vi; /* struct that stores all the static vorbis bitstream
- settings */
- vorbis_comment vc; /* struct that stores all the user comments */
-
- vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
- vorbis_block vb; /* local working space for packet->PCM decode */
-
- gboolean managed;
- gint bitrate;
- gint min_bitrate;
- gint max_bitrate;
- gfloat quality;
- gboolean quality_set;
-
- gint channels;
- gint frequency;
-
- guint64 samples_in;
- guint64 bytes_out;
- GstClockTime next_ts;
- GstClockTime expected_ts;
- gboolean next_discont;
- guint64 granulepos_offset;
- gint64 subgranule_offset;
-
- GstTagList * tags;
-
- gboolean setup;
- gboolean header_sent;
- gchar *last_message;
-};
-
-struct _GstVorbisEncClass {
- GstElementClass parent_class;
-};
-
-GType gst_vorbis_enc_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_ENC_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbisparse.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,666 +0,0 @@
-/* GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- * Copyright (C) 2006 Andy Wingo <wingo@pobox.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.
- */
-
-/**
- * SECTION:element-vorbisparse
- * @short_description: parses vorbis streams
- * @see_also: vorbisdec, oggdemux, theoraparse
- *
- * <refsect2>
- * <para>
- * The vorbisparse element will parse the header packets of the Vorbis
- * stream and put them as the streamheader in the caps. This is used in the
- * multifdsink case where you want to stream live vorbis streams to multiple
- * clients, each client has to receive the streamheaders first before they can
- * consume the vorbis packets.
- * </para>
- * <para>
- * This element also makes sure that the buffers that it pushes out are properly
- * timestamped and that their offset and offset_end are set. The buffers that
- * vorbisparse outputs have all of the metadata that oggmux expects to receive,
- * which allows you to (for example) remux an ogg/vorbis file.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisparse ! fakesink
- * </programlisting>
- * This pipeline shows that the streamheader is set in the caps, and that each
- * buffer has the timestamp, duration, offset, and offset_end set.
- * </para>
- * <para>
- * <programlisting>
- * gst-launch filesrc location=sine.ogg ! oggdemux ! vorbisparse \
- * ! oggmux ! filesink location=sine-remuxed.ogg
- * </programlisting>
- * This pipeline shows remuxing. sine-remuxed.ogg might not be exactly the same
- * as sine.ogg, but they should produce exactly the same decoded data.
- * </para>
- * </refsect2>
- *
- * Last reviewed on 2006-04-01 (0.10.4.1)
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "vorbisparse.h"
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug);
-#define GST_CAT_DEFAULT vorbisparse_debug
-
-static const GstElementDetails vorbis_parse_details = {
- "VorbisParse",
- "Codec/Parser/Audio",
- "parse raw vorbis streams",
- "Thomas Vander Stichele <thomas at apestaart dot org>"
-};
-
-static GstStaticPadTemplate vorbis_parse_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-vorbis")
- );
-
-static GstStaticPadTemplate vorbis_parse_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-vorbis")
- );
-
-GST_BOILERPLATE (GstVorbisParse, gst_vorbis_parse, GstElement,
- GST_TYPE_ELEMENT);
-
-static GstFlowReturn vorbis_parse_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn vorbis_parse_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean vorbis_parse_sink_event (GstPad * pad, GstEvent * event);
-static gboolean vorbis_parse_src_query (GstPad * pad, GstQuery * query);
-static gboolean vorbis_parse_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value);
-static GstFlowReturn vorbis_parse_parse_packet (GstVorbisParse * parse,
- GstBuffer * buf);
-
-static void
-gst_vorbis_parse_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&vorbis_parse_src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&vorbis_parse_sink_factory));
- gst_element_class_set_details (element_class, &vorbis_parse_details);
-}
-
-static void
-gst_vorbis_parse_class_init (GstVorbisParseClass * klass)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- gstelement_class->change_state = vorbis_parse_change_state;
-
- klass->parse_packet = GST_DEBUG_FUNCPTR (vorbis_parse_parse_packet);
-}
-
-static void
-gst_vorbis_parse_init (GstVorbisParse * parse, GstVorbisParseClass * g_class)
-{
- parse->sinkpad =
- gst_pad_new_from_static_template (&vorbis_parse_sink_factory, "sink");
- gst_pad_set_chain_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (vorbis_parse_chain));
- gst_pad_set_event_function (parse->sinkpad,
- GST_DEBUG_FUNCPTR (vorbis_parse_sink_event));
- gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);
-
- parse->srcpad =
- gst_pad_new_from_static_template (&vorbis_parse_src_factory, "src");
- gst_pad_set_query_function (parse->srcpad,
- GST_DEBUG_FUNCPTR (vorbis_parse_src_query));
- gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
-}
-
-static void
-vorbis_parse_set_header_on_caps (GstVorbisParse * parse, GstCaps * caps)
-{
- GstBuffer *buf1, *buf2, *buf3;
- GstStructure *structure;
- GValue array = { 0 };
- GValue value = { 0 };
-
- g_assert (parse);
- g_assert (parse->streamheader);
- g_assert (parse->streamheader->next);
- g_assert (parse->streamheader->next->next);
- buf1 = parse->streamheader->data;
- g_assert (buf1);
- buf2 = parse->streamheader->next->data;
- g_assert (buf2);
- buf3 = parse->streamheader->next->next->data;
- g_assert (buf3);
-
- structure = gst_caps_get_structure (caps, 0);
-
- /* mark buffers */
- GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS);
- GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS);
-
- /* put buffers in a fixed list */
- g_value_init (&array, GST_TYPE_ARRAY);
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf1);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf2);
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_set_buffer (&value, buf3);
- gst_value_array_append_value (&array, &value);
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&value);
- g_value_unset (&array);
-}
-
-static void
-vorbis_parse_drain_event_queue (GstVorbisParse * parse)
-{
- while (parse->event_queue->length) {
- GstEvent *event;
-
- event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
- gst_pad_event_default (parse->sinkpad, event);
- }
-}
-
-static void
-vorbis_parse_push_headers (GstVorbisParse * parse)
-{
- /* mark and put on caps */
- GstCaps *caps;
- GstBuffer *outbuf, *outbuf1, *outbuf2, *outbuf3;
- ogg_packet packet;
-
- /* get the headers into the caps, passing them to vorbis as we go */
- caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad));
- vorbis_parse_set_header_on_caps (parse, caps);
- GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
- gst_pad_set_caps (parse->srcpad, caps);
- gst_caps_unref (caps);
-
- outbuf = GST_BUFFER_CAST (parse->streamheader->data);
- packet.packet = GST_BUFFER_DATA (outbuf);
- packet.bytes = GST_BUFFER_SIZE (outbuf);
- packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
- packet.packetno = 1;
- packet.e_o_s = 0;
- packet.b_o_s = 1;
- vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
- parse->sample_rate = parse->vi.rate;
- outbuf1 = outbuf;
-
- outbuf = GST_BUFFER_CAST (parse->streamheader->next->data);
- packet.packet = GST_BUFFER_DATA (outbuf);
- packet.bytes = GST_BUFFER_SIZE (outbuf);
- packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
- packet.packetno = 2;
- packet.e_o_s = 0;
- packet.b_o_s = 0;
- vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
- outbuf2 = outbuf;
-
- outbuf = GST_BUFFER_CAST (parse->streamheader->next->next->data);
- packet.packet = GST_BUFFER_DATA (outbuf);
- packet.bytes = GST_BUFFER_SIZE (outbuf);
- packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
- packet.packetno = 3;
- packet.e_o_s = 0;
- packet.b_o_s = 0;
- vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
- outbuf3 = outbuf;
-
- /* first process queued events */
- vorbis_parse_drain_event_queue (parse);
-
- /* push out buffers, ignoring return value... */
- gst_buffer_set_caps (outbuf1, GST_PAD_CAPS (parse->srcpad));
- gst_pad_push (parse->srcpad, outbuf1);
- gst_buffer_set_caps (outbuf2, GST_PAD_CAPS (parse->srcpad));
- gst_pad_push (parse->srcpad, outbuf2);
- gst_buffer_set_caps (outbuf3, GST_PAD_CAPS (parse->srcpad));
- gst_pad_push (parse->srcpad, outbuf3);
-
- g_list_free (parse->streamheader);
- parse->streamheader = NULL;
-
- parse->streamheader_sent = TRUE;
-}
-
-static void
-vorbis_parse_clear_queue (GstVorbisParse * parse)
-{
- while (parse->buffer_queue->length) {
- GstBuffer *buf;
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
- gst_buffer_unref (buf);
- }
- while (parse->event_queue->length) {
- GstEvent *event;
-
- event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue));
- gst_event_unref (event);
- }
-}
-
-static GstFlowReturn
-vorbis_parse_push_buffer (GstVorbisParse * parse, GstBuffer * buf,
- gint64 granulepos)
-{
- guint64 samples;
-
- /* our hack as noted below */
- samples = GST_BUFFER_OFFSET (buf);
-
- GST_BUFFER_OFFSET_END (buf) = granulepos;
- GST_BUFFER_DURATION (buf) = samples * GST_SECOND / parse->sample_rate;
- GST_BUFFER_OFFSET (buf) = granulepos * GST_SECOND / parse->sample_rate;
- GST_BUFFER_TIMESTAMP (buf) =
- GST_BUFFER_OFFSET (buf) - GST_BUFFER_DURATION (buf);
-
- gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
-
- return gst_pad_push (parse->srcpad, buf);
-}
-
-static GstFlowReturn
-vorbis_parse_drain_queue_prematurely (GstVorbisParse * parse)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- gint64 granulepos = MAX (parse->prev_granulepos, 0);
-
- /* got an EOS event, make sure to push out any buffers that were in the queue
- * -- won't normally be the case, but this catches the
- * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous
- * stream. */
-
- /* if we got EOS before any buffers came, go ahead and push the other events
- * first */
- vorbis_parse_drain_event_queue (parse);
-
- while (!g_queue_is_empty (parse->buffer_queue)) {
- GstBuffer *buf;
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
- granulepos += GST_BUFFER_OFFSET (buf);
- ret = vorbis_parse_push_buffer (parse, buf, granulepos);
-
- if (ret != GST_FLOW_OK)
- goto done;
- }
-
- parse->prev_granulepos = granulepos;
-
-done:
- return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_drain_queue (GstVorbisParse * parse, gint64 granulepos)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GList *walk;
- gint64 cur = granulepos;
- gint64 gp;
-
- for (walk = parse->buffer_queue->head; walk; walk = walk->next)
- cur -= GST_BUFFER_OFFSET (walk->data);
-
- if (parse->prev_granulepos != -1)
- cur = MAX (cur, parse->prev_granulepos);
-
- while (!g_queue_is_empty (parse->buffer_queue)) {
- GstBuffer *buf;
-
- buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue));
-
- cur += GST_BUFFER_OFFSET (buf);
- gp = CLAMP (cur, 0, granulepos);
-
- ret = vorbis_parse_push_buffer (parse, buf, gp);
-
- if (ret != GST_FLOW_OK)
- goto done;
- }
-
- parse->prev_granulepos = granulepos;
-
-done:
- return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- long blocksize;
- ogg_packet packet;
-
- buf = gst_buffer_make_metadata_writable (buf);
-
- packet.packet = GST_BUFFER_DATA (buf);
- packet.bytes = GST_BUFFER_SIZE (buf);
- packet.granulepos = GST_BUFFER_OFFSET_END (buf);
- packet.packetno = parse->packetno + parse->buffer_queue->length;
- packet.e_o_s = 0;
-
- blocksize = vorbis_packet_blocksize (&parse->vi, &packet);
-
- /* temporarily store the sample count in OFFSET -- we overwrite this later */
-
- if (parse->prev_blocksize < 0)
- GST_BUFFER_OFFSET (buf) = 0;
- else
- GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4;
-
- parse->prev_blocksize = blocksize;
-
- g_queue_push_tail (parse->buffer_queue, buf);
-
- if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
- ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));
-
- return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_parse_packet (GstVorbisParse * parse, GstBuffer * buf)
-{
- GstFlowReturn ret;
-
- parse->packetno++;
-
- if (parse->packetno <= 3) {
- /* if 1 <= packetno <= 3, it's streamheader,
- * so put it on the streamheader list and return */
- parse->streamheader = g_list_append (parse->streamheader, buf);
- ret = GST_FLOW_OK;
- } else {
- if (!parse->streamheader_sent)
- vorbis_parse_push_headers (parse);
-
- ret = vorbis_parse_queue_buffer (parse, buf);
- }
-
- return ret;
-}
-
-static GstFlowReturn
-vorbis_parse_chain (GstPad * pad, GstBuffer * buffer)
-{
- GstVorbisParseClass *klass;
- GstVorbisParse *parse;
-
- parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
- klass = GST_VORBIS_PARSE_CLASS (G_OBJECT_GET_CLASS (parse));
-
- g_assert (klass->parse_packet != NULL);
-
- return klass->parse_packet (parse, buffer);
-}
-
-static gboolean
-vorbis_parse_queue_event (GstVorbisParse * parse, GstEvent * event)
-{
- GstFlowReturn ret = TRUE;
-
- g_queue_push_tail (parse->event_queue, event);
-
- return ret;
-}
-
-static gboolean
-vorbis_parse_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret;
- GstVorbisParse *parse;
-
- parse = GST_VORBIS_PARSE (gst_pad_get_parent (pad));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_START:
- vorbis_parse_clear_queue (parse);
- parse->prev_granulepos = -1;
- parse->prev_blocksize = -1;
- ret = gst_pad_event_default (pad, event);
- break;
- case GST_EVENT_EOS:
- vorbis_parse_drain_queue_prematurely (parse);
- ret = gst_pad_event_default (pad, event);
- break;
- default:
- if (!parse->streamheader_sent && GST_EVENT_IS_SERIALIZED (event))
- ret = vorbis_parse_queue_event (parse, event);
- else
- ret = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (parse);
-
- return ret;
-}
-
-static gboolean
-vorbis_parse_convert (GstPad * pad,
- GstFormat src_format, gint64 src_value,
- GstFormat * dest_format, gint64 * dest_value)
-{
- gboolean res = TRUE;
- GstVorbisParse *parse;
- guint64 scale = 1;
-
- parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
-
- /* fixme: assumes atomic access to lots of instance variables modified from
- * the streaming thread, including 64-bit variables */
-
- if (parse->packetno < 4)
- return FALSE;
-
- if (src_format == *dest_format) {
- *dest_value = src_value;
- return TRUE;
- }
-
- if (parse->sinkpad == pad &&
- (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
- return FALSE;
-
- switch (src_format) {
- case GST_FORMAT_TIME:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- scale = sizeof (float) * parse->vi.channels;
- case GST_FORMAT_DEFAULT:
- *dest_value =
- scale * gst_util_uint64_scale_int (src_value, parse->vi.rate,
- GST_SECOND);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_DEFAULT:
- switch (*dest_format) {
- case GST_FORMAT_BYTES:
- *dest_value = src_value * sizeof (float) * parse->vi.channels;
- break;
- case GST_FORMAT_TIME:
- *dest_value =
- gst_util_uint64_scale_int (src_value, GST_SECOND, parse->vi.rate);
- break;
- default:
- res = FALSE;
- }
- break;
- case GST_FORMAT_BYTES:
- switch (*dest_format) {
- case GST_FORMAT_DEFAULT:
- *dest_value = src_value / (sizeof (float) * parse->vi.channels);
- break;
- case GST_FORMAT_TIME:
- *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
- parse->vi.rate * sizeof (float) * parse->vi.channels);
- break;
- default:
- res = FALSE;
- }
- break;
- default:
- res = FALSE;
- }
-
- return res;
-}
-
-static gboolean
-vorbis_parse_src_query (GstPad * pad, GstQuery * query)
-{
- gint64 granulepos;
- GstVorbisParse *parse;
- gboolean res = FALSE;
-
- parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_POSITION:
- {
- GstFormat format;
- gint64 value;
-
- granulepos = parse->prev_granulepos;
-
- gst_query_parse_position (query, &format, NULL);
-
- /* and convert to the final format */
- if (!(res =
- vorbis_parse_convert (pad, GST_FORMAT_DEFAULT, granulepos,
- &format, &value)))
- goto error;
-
- /* fixme: support segments
- value = (value - parse->segment_start) + parse->segment_time;
- */
-
- gst_query_set_position (query, format, value);
-
- GST_LOG_OBJECT (parse, "query %p: peer returned granulepos: %"
- G_GUINT64_FORMAT " - we return %" G_GUINT64_FORMAT " (format %u)",
- query, granulepos, value, format);
-
- break;
- }
- case GST_QUERY_DURATION:
- {
- /* fixme: not threadsafe */
- /* query peer for total length */
- if (!gst_pad_is_linked (parse->sinkpad)) {
- GST_WARNING_OBJECT (parse, "sink pad %" GST_PTR_FORMAT " is not linked",
- parse->sinkpad);
- goto error;
- }
- if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query)))
- goto error;
- break;
- }
- case GST_QUERY_CONVERT:
- {
- GstFormat src_fmt, dest_fmt;
- gint64 src_val, dest_val;
-
- gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
- if (!(res =
- vorbis_parse_convert (pad, src_fmt, src_val, &dest_fmt,
- &dest_val)))
- goto error;
- gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
- return res;
-
-error:
- {
- GST_WARNING_OBJECT (parse, "error handling query");
- return res;
- }
-}
-
-static GstStateChangeReturn
-vorbis_parse_change_state (GstElement * element, GstStateChange transition)
-{
- GstVorbisParse *parse = GST_VORBIS_PARSE (element);
- GstStateChangeReturn ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- vorbis_info_init (&parse->vi);
- vorbis_comment_init (&parse->vc);
- parse->prev_granulepos = -1;
- parse->prev_blocksize = -1;
- parse->packetno = 0;
- parse->streamheader_sent = FALSE;
- parse->buffer_queue = g_queue_new ();
- parse->event_queue = g_queue_new ();
- break;
- default:
- break;
- }
-
- ret = parent_class->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- vorbis_info_clear (&parse->vi);
- vorbis_comment_clear (&parse->vc);
- vorbis_parse_clear_queue (parse);
- g_queue_free (parse->buffer_queue);
- parse->buffer_queue = NULL;
- g_queue_free (parse->event_queue);
- parse->event_queue = NULL;
- break;
- default:
- break;
- }
-
- return ret;
-}
--- a/gst_plugins_base/ext/vorbis/vorbisparse.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2004> Thomas Vander Stichele <thomas at apestaart dot org>
- *
- * 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 __GST_VORBIS_PARSE_H__
-#define __GST_VORBIS_PARSE_H__
-
-
-#include <gst/gst.h>
-#include <vorbis/codec.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_VORBIS_PARSE \
- (gst_vorbis_parse_get_type())
-#define GST_VORBIS_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_PARSE,GstVorbisParse))
-#define GST_VORBIS_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_PARSE,GstVorbisParseClass))
-#define GST_IS_VORBIS_PARSE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_PARSE))
-#define GST_IS_VORBIS_PARSE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_PARSE))
-
-typedef struct _GstVorbisParse GstVorbisParse;
-typedef struct _GstVorbisParseClass GstVorbisParseClass;
-
-/**
- * GstVorbisParse:
- *
- * Opaque data structure.
- */
-struct _GstVorbisParse {
- GstElement element;
-
- GstPad * sinkpad;
- GstPad * srcpad;
-
- guint packetno;
- gboolean streamheader_sent;
- GList * streamheader;
-
- GQueue * event_queue;
- GQueue * buffer_queue;
-
- vorbis_info vi;
- vorbis_comment vc;
-
- gint64 prev_granulepos;
- gint32 prev_blocksize;
- guint32 sample_rate;
-};
-
-struct _GstVorbisParseClass {
- GstElementClass parent_class;
-
- /* virtual functions */
- GstFlowReturn (*parse_packet) (GstVorbisParse * parse, GstBuffer * buf);
-};
-
-GType gst_vorbis_parse_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_PARSE_H__ */
--- a/gst_plugins_base/ext/vorbis/vorbistag.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2006 James Livingston <doclivingston@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.
- */
-
-/**
- * SECTION:element-vorbistag
- * @see_also: #oggdemux, #oggmux, #vorbisparse, #GstTagSetter
- * @short_description: retags vorbis streams
- *
- * <refsect2>
- * <para>
- * The vorbistags element can change the tag contained within a raw
- * vorbis stream. Specifically, it modifies the comments header packet
- * of the vorbis stream.
- * </para>
- * <para>
- * The element will also process the stream as the #vorbisparse element does
- * so it can be used when remuxing an Ogg Vorbis stream, without additional
- * elements.
- * </para>
- * <para>
- * Applications can set the tags to write using the #GstTagSetter interface.
- * Tags contained withing the vorbis bitstream will be picked up
- * automatically (and merged according to the merge mode set via the tag
- * setter interface).
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * This element is not useful with gst-launch, because it does not support
- * setting the tags on a #GstTagSetter interface. Conceptually, the element
- * will usually be used like:
- * <programlisting>
- * gst-launch -v filesrc location=foo.ogg ! oggdemux ! vorbistag ! oggmux ! filesink location=bar.ogg
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <glib.h>
-#include <gst/tag/tag.h>
-#include <gst/gsttagsetter.h>
-
-#include <vorbis/codec.h>
-
-#include "vorbistag.h"
-
-
-GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug);
-#define GST_CAT_DEFAULT vorbisparse_debug
-
-static void gst_vorbis_tag_base_init (gpointer g_class);
-static void gst_vorbis_tag_class_init (GstVorbisTagClass * klass);
-static void gst_vorbis_tag_init (GstVorbisTag * tagger,
- GstVorbisTagClass * g_class);
-static GstFlowReturn gst_vorbis_tag_parse_packet (GstVorbisParse * parse,
- GstBuffer * buffer);
-
-#define _do_init(type) \
- G_STMT_START{ \
- static const GInterfaceInfo tag_setter_info = { \
- NULL, \
- NULL, \
- NULL \
- }; \
- g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, \
- &tag_setter_info); \
- }G_STMT_END
-
-GST_BOILERPLATE_FULL (GstVorbisTag, gst_vorbis_tag, GstVorbisParse,
- GST_TYPE_VORBIS_PARSE, _do_init);
-
-static GstElementDetails vorbis_tag_details = {
- "VorbisTag",
- "Formatter/Metadata",
- "Retags vorbis streams",
- "James Livingston <doclivingston@gmail.com>"
-};
-
-
-static void
-gst_vorbis_tag_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &vorbis_tag_details);
-}
-
-static void
-gst_vorbis_tag_class_init (GstVorbisTagClass * klass)
-{
- GstVorbisParseClass *vorbisparse_class = GST_VORBIS_PARSE_CLASS (klass);
-
- vorbisparse_class->parse_packet = gst_vorbis_tag_parse_packet;
-}
-
-static void
-gst_vorbis_tag_init (GstVorbisTag * tagger, GstVorbisTagClass * g_class)
-{
- /* nothing to do */
-}
-
-
-static GstFlowReturn
-gst_vorbis_tag_parse_packet (GstVorbisParse * parse, GstBuffer * buffer)
-{
- GstTagList *old_tags, *new_tags;
- const GstTagList *user_tags;
- GstVorbisTag *tagger;
- gchar *encoder = NULL;
- GstBuffer *new_buf;
-
- /* just pass everything except the comments packet */
- if (GST_BUFFER_SIZE (buffer) >= 1 && GST_BUFFER_DATA (buffer)[0] != 0x03) {
- return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);
- }
-
- tagger = GST_VORBIS_TAG (parse);
-
- old_tags =
- gst_tag_list_from_vorbiscomment_buffer (buffer, (guint8 *) "\003vorbis",
- 7, &encoder);
- user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tagger));
-
- /* build new tag list */
- new_tags = gst_tag_list_merge (user_tags, old_tags,
- gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tagger)));
- gst_tag_list_free (old_tags);
-
- new_buf =
- gst_tag_list_to_vorbiscomment_buffer (new_tags, (guint8 *) "\003vorbis",
- 7, encoder);
- gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS);
-
- gst_tag_list_free (new_tags);
- g_free (encoder);
- gst_buffer_unref (buffer);
-
- return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, new_buf);
-}
--- a/gst_plugins_base/ext/vorbis/vorbistag.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* -*- c-basic-offset: 2 -*-
- * GStreamer
- * Copyright (C) <2006> James Livingston <doclivingston@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.
- */
-
-
-#ifndef __GST_VORBIS_TAG_H__
-#define __GST_VORBIS_TAG_H__
-
-#include "vorbisparse.h"
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_VORBIS_TAG \
- (gst_vorbis_tag_get_type())
-#define GST_VORBIS_TAG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_TAG,GstVorbisTag))
-#define GST_VORBIS_TAG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_TAG,GstVorbisTagClass))
-#define GST_IS_VORBIS_TAG(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_TAG))
-#define GST_IS_VORBIS_TAG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_TAG))
-
-
-typedef struct _GstVorbisTag GstVorbisTag;
-typedef struct _GstVorbisTagClass GstVorbisTagClass;
-
-/**
- * GstVorbisTag:
- *
- * Opaque data structure.
- */
-struct _GstVorbisTag {
- GstVorbisParse parse;
-};
-
-struct _GstVorbisTagClass {
- GstVorbisParseClass parent_class;
-};
-
-GType gst_vorbis_tag_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_VORBIS_TAG_H__ */
--- a/gst_plugins_base/group/bld.inf Fri May 28 18:11:17 2010 -0500
+++ b/gst_plugins_base/group/bld.inf Fri Jun 25 17:18:46 2010 -0500
@@ -4,166 +4,166 @@
PRJ_EXPORTS
// interfaces
-../gst-libs/gst/interfaces/colorbalance.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/colorbalance.h
-../gst-libs/gst/interfaces/colorbalancechannel.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/colorbalancechannel.h
-../gst-libs/gst/interfaces/mixer.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/mixer.h
-../gst-libs/gst/interfaces/mixeroptions.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/mixeroptions.h
-../gst-libs/gst/interfaces/mixertrack.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/mixertrack.h
-../gst-libs/gst/interfaces/navigation.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/navigation.h
-../gst-libs/gst/interfaces/propertyprobe.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/propertyprobe.h
-../gst-libs/gst/interfaces/tuner.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/tuner.h
-../gst-libs/gst/interfaces/tunernorm.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/tunernorm.h
-../gst-libs/gst/interfaces/tunerchannel.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/tunerchannel.h
-../gst-libs/gst/interfaces/xoverlay.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/xoverlay.h
-../gst-libs/gst/interfaces/interfaces-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/interfaces-enumtypes.h
+../gst-libs/gst/interfaces/colorbalance.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/colorbalance.h)
+../gst-libs/gst/interfaces/colorbalancechannel.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/colorbalancechannel.h)
+../gst-libs/gst/interfaces/mixer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/mixer.h)
+../gst-libs/gst/interfaces/mixeroptions.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/mixeroptions.h)
+../gst-libs/gst/interfaces/mixertrack.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/mixertrack.h)
+../gst-libs/gst/interfaces/navigation.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/navigation.h)
+../gst-libs/gst/interfaces/propertyprobe.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/propertyprobe.h)
+../gst-libs/gst/interfaces/tuner.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/tuner.h)
+../gst-libs/gst/interfaces/tunernorm.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/tunernorm.h)
+../gst-libs/gst/interfaces/tunerchannel.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/tunerchannel.h)
+../gst-libs/gst/interfaces/xoverlay.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/xoverlay.h)
+../gst-libs/gst/interfaces/interfaces-enumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/interfaces/interfaces-enumtypes.h)
// audio
-../gst-libs/gst/audio/audio.h /epoc32/include/platform/mw/gstreamer/gst/audio/audio.h
-../gst-libs/gst/audio/gstaudioclock.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstaudioclock.h
-../gst-libs/gst/audio/gstaudiofilter.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstaudiofilter.h
-../gst-libs/gst/audio/gstaudiosink.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstaudiosink.h
-../gst-libs/gst/audio/gstaudiosrc.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstaudiosrc.h
-../gst-libs/gst/audio/gstbaseaudiosink.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstbaseaudiosink.h
-../gst-libs/gst/audio/gstbaseaudiosrc.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstbaseaudiosrc.h
-../gst-libs/gst/audio/gstringbuffer.h /epoc32/include/platform/mw/gstreamer/gst/audio/gstringbuffer.h
-../gst-libs/gst/audio/mixerutils.h /epoc32/include/platform/mw/gstreamer/gst/audio/mixerutils.h
-../gst-libs/gst/audio/multichannel.h /epoc32/include/platform/mw/gstreamer/gst/audio/multichannel.h
-../gst-libs/gst/audio/audio-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/audio/audio-enumtypes.h
+../gst-libs/gst/audio/audio.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/audio.h)
+../gst-libs/gst/audio/gstaudioclock.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstaudioclock.h)
+../gst-libs/gst/audio/gstaudiofilter.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstaudiofilter.h)
+../gst-libs/gst/audio/gstaudiosink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstaudiosink.h)
+../gst-libs/gst/audio/gstaudiosrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstaudiosrc.h)
+../gst-libs/gst/audio/gstbaseaudiosink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstbaseaudiosink.h)
+../gst-libs/gst/audio/gstbaseaudiosrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstbaseaudiosrc.h)
+../gst-libs/gst/audio/gstringbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/gstringbuffer.h)
+../gst-libs/gst/audio/mixerutils.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/mixerutils.h)
+../gst-libs/gst/audio/multichannel.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/multichannel.h)
+../gst-libs/gst/audio/audio-enumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audio/audio-enumtypes.h)
// cdda
-//../gst-libs/gst/cdda/base64.h /epoc32/include/platform/mw/gstreamer/gst/cdda/base64.h
-../gst-libs/gst/cdda/gstcddabasesrc.h /epoc32/include/platform/mw/gstreamer/gst/cdda/gstcddabasesrc.h
+//../gst-libs/gst/cdda/base64.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/cdda/base64.h)
+../gst-libs/gst/cdda/gstcddabasesrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/cdda/gstcddabasesrc.h)
// floatcast
-../gst-libs/gst/floatcast/floatcast.h /epoc32/include/platform/mw/gstreamer/gst/floatcast/floatcast.h
+../gst-libs/gst/floatcast/floatcast.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/floatcast/floatcast.h)
// riff
-../gst-libs/gst/riff/riff-ids.h /epoc32/include/platform/mw/gstreamer/gst/riff/riff-ids.h
-../gst-libs/gst/riff/riff-media.h /epoc32/include/platform/mw/gstreamer/gst/riff/riff-media.h
-../gst-libs/gst/riff/riff-read.h /epoc32/include/platform/mw/gstreamer/gst/riff/riff-read.h
+../gst-libs/gst/riff/riff-ids.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/riff/riff-ids.h)
+../gst-libs/gst/riff/riff-media.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/riff/riff-media.h)
+../gst-libs/gst/riff/riff-read.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/riff/riff-read.h)
//app
-../gst-libs/gst/app/gstappbuffer.h /epoc32/include/platform/mw/gstreamer/gst/app/gstappbuffer.h
-../gst-libs/gst/app/gstappsink.h /epoc32/include/platform/mw/gstreamer/gst/app/gstappsink.h
-../gst-libs/gst/app/gstappsrc.h /epoc32/include/platform/mw/gstreamer/gst/app/gstappsrc.h
+../gst-libs/gst/app/gstappbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/app/gstappbuffer.h)
+../gst-libs/gst/app/gstappsink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/app/gstappsink.h)
+../gst-libs/gst/app/gstappsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/app/gstappsrc.h)
// rtp
-../gst-libs/gst/rtp/gstbasertpdepayload.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstbasertpdepayload.h
-../gst-libs/gst/rtp/gstbasertppayload.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstbasertppayload.h
-../gst-libs/gst/rtp/gstrtpbuffer.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstrtpbuffer.h
-../gst-libs/gst/rtp/gstbasertpaudiopayload.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstbasertpaudiopayload.h
-../gst-libs/gst/rtp/gstrtcpbuffer.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstrtcpbuffer.h
-../gst-libs/gst/rtp/gstrtppayloads.h /epoc32/include/platform/mw/gstreamer/gst/rtp/gstrtppayloads.h
+../gst-libs/gst/rtp/gstbasertpdepayload.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstbasertpdepayload.h)
+../gst-libs/gst/rtp/gstbasertppayload.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstbasertppayload.h)
+../gst-libs/gst/rtp/gstrtpbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstrtpbuffer.h)
+../gst-libs/gst/rtp/gstbasertpaudiopayload.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstbasertpaudiopayload.h)
+../gst-libs/gst/rtp/gstrtcpbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstrtcpbuffer.h)
+../gst-libs/gst/rtp/gstrtppayloads.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/rtp/gstrtppayloads.h)
// tag
-//../gst-libs/gst/tag/gsttageditingprivate.h /epoc32/include/platform/mw/gstreamer/gst/tag/gsttageditingprivate.h
-../gst-libs/gst/tag/tag.h /epoc32/include/platform/mw/gstreamer/gst/tag/tag.h
+//../gst-libs/gst/tag/gsttageditingprivate.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tag/gsttageditingprivate.h)
+../gst-libs/gst/tag/tag.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tag/tag.h)
// netbuffer
-../gst-libs/gst/netbuffer/gstnetbuffer.h /epoc32/include/platform/mw/gstreamer/gst/netbuffer/gstnetbuffer.h
+../gst-libs/gst/netbuffer/gstnetbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/netbuffer/gstnetbuffer.h)
// video
-../gst-libs/gst/video/gstvideofilter.h /epoc32/include/platform/mw/gstreamer/gst/video/gstvideofilter.h
-../gst-libs/gst/video/gstvideosink.h /epoc32/include/platform/mw/gstreamer/gst/video/gstvideosink.h
-../gst-libs/gst/video/video.h /epoc32/include/platform/mw/gstreamer/gst/video/video.h
-../gst-libs/gst/video/video-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/video/video-enumtypes.h
+../gst-libs/gst/video/gstvideofilter.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/video/gstvideofilter.h)
+../gst-libs/gst/video/gstvideosink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/video/gstvideosink.h)
+../gst-libs/gst/video/video.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/video/video.h)
+../gst-libs/gst/video/video-enumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/video/video-enumtypes.h)
// adder
-//../gst/adder/gstadder.h /epoc32/include/platform/mw/gstreamer/gst/adder/gstadder.h
+//../gst/adder/gstadder.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/adder/gstadder.h)
// audioconvert
-//../gst/audioconvert/audioconvert.h /epoc32/include/platform/mw/gstreamer/gst/audioconvert/audioconvert.h
-//../gst/audioconvert/gstaudioconvert.h /epoc32/include/platform/mw/gstreamer/gst/audioconvert/gstaudioconvert.h
-//../gst/audioconvert/gstchannelmix.h /epoc32/include/platform/mw/gstreamer/gst/audioconvert/gstchannelmix.h
-//../gst/audioconvert/plugin.h /epoc32/include/platform/mw/gstreamer/gst/audioconvert/plugin.h
+//../gst/audioconvert/audioconvert.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioconvert/audioconvert.h)
+//../gst/audioconvert/gstaudioconvert.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioconvert/gstaudioconvert.h)
+//../gst/audioconvert/gstchannelmix.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioconvert/gstchannelmix.h)
+//../gst/audioconvert/plugin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioconvert/plugin.h)
// audioresample
-//../gst/audioresample/buffer.h /epoc32/include/platform/mw/gstreamer/gst/audioresample/buffer.h
-//../gst/audioresample/debug.h /epoc32/include/platform/mw/gstreamer/gst/audioresample/debug.h
-//../gst/audioresample/functable.h /epoc32/include/platform/mw/gstreamer/gst/audioresample/functable.h
-//../gst/audioresample/gstaudioresample.h /epoc32/include/platform/mw/gstreamer/gst/audioresample/gstaudioresample.h
-//../gst/audioresample/resample.h /epoc32/include/platform/mw/gstreamer/gst/audioresample/resample.h
+//../gst/audioresample/buffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioresample/buffer.h)
+//../gst/audioresample/debug.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioresample/debug.h)
+//../gst/audioresample/functable.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioresample/functable.h)
+//../gst/audioresample/gstaudioresample.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioresample/gstaudioresample.h)
+//../gst/audioresample/resample.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audioresample/resample.h)
// audiotestsrc
-//../gst/audiotestsrc/gstaudiotestsrc.h /epoc32/include/platform/mw/gstreamer/gst/audiotestsrc/gstaudiotestsrc.h
+//../gst/audiotestsrc/gstaudiotestsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/audiotestsrc/gstaudiotestsrc.h)
// ffmpegcolorspace
-//../gst/ffmpegcolorspace/avcodec.h /epoc32/include/platform/mw/gstreamer/gst/ffmpegcolorspace/avcodec.h
-//../gst/ffmpegcolorspace/dsputil.h /epoc32/include/platform/mw/gstreamer/gst/ffmpegcolorspace/dsputil.h
-//../gst/ffmpegcolorspace/gstffmpegcodecmap.h /epoc32/include/platform/mw/gstreamer/gst/ffmpegcolorspace/gstffmpegcodecmap.h
-//../gst/ffmpegcolorspace/gstffmpegcolorspace.h /epoc32/include/platform/mw/gstreamer/gst/ffmpegcolorspace/gstffmpegcolorspace.h
-//../gst/ffmpegcolorspace/imgconvert_template.h /epoc32/include/platform/mw/gstreamer/gst/ffmpegcolorspace/imgconvert_template.h
+//../gst/ffmpegcolorspace/avcodec.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/ffmpegcolorspace/avcodec.h)
+//../gst/ffmpegcolorspace/dsputil.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/ffmpegcolorspace/dsputil.h)
+//../gst/ffmpegcolorspace/gstffmpegcodecmap.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/ffmpegcolorspace/gstffmpegcodecmap.h)
+//../gst/ffmpegcolorspace/gstffmpegcolorspace.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/ffmpegcolorspace/gstffmpegcolorspace.h)
+//../gst/ffmpegcolorspace/imgconvert_template.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/ffmpegcolorspace/imgconvert_template.h)
// playback
-//../gst/playback/gstplay-marshal.h /epoc32/include/platform/mw/gstreamer/gst/playback/gstplay-marshal.h
-//../gst/playback/gstplaybasebin.h /epoc32/include/platform/mw/gstreamer/gst/playback/gstplaybasebin.h
-//../gst/playback/gststreaminfo.h /epoc32/include/platform/mw/gstreamer/gst/playback/gststreaminfo.h
-//../gst/playback/gststreamselector.h /epoc32/include/platform/mw/gstreamer/gst/playback/gststreamselector.h
+//../gst/playback/gstplay-marshal.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/playback/gstplay-marshal.h)
+//../gst/playback/gstplaybasebin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/playback/gstplaybasebin.h)
+//../gst/playback/gststreaminfo.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/playback/gststreaminfo.h)
+//../gst/playback/gststreamselector.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/playback/gststreamselector.h)
//pbutils
-../gst-libs/gst/pbutils/pbutils.h /epoc32/include/platform/mw/gstreamer/gst/pbutils/pbutils.h
-../gst-libs/gst/pbutils/descriptions.h /epoc32/include/platform/mw/gstreamer/gst/pbutils/descriptions.h
-../gst-libs/gst/pbutils/install-plugins.h /epoc32/include/platform/mw/gstreamer/gst/pbutils/install-plugins.h
-../gst-libs/gst/pbutils/missing-plugins.h /epoc32/include/platform/mw/gstreamer/gst/pbutils/missing-plugins.h
-../gst-libs/gst/pbutils/pbutils-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/pbutils/pbutils-enumtypes.h
+../gst-libs/gst/pbutils/pbutils.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/pbutils/pbutils.h)
+../gst-libs/gst/pbutils/descriptions.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/pbutils/descriptions.h)
+../gst-libs/gst/pbutils/install-plugins.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/pbutils/install-plugins.h)
+../gst-libs/gst/pbutils/missing-plugins.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/pbutils/missing-plugins.h)
+../gst-libs/gst/pbutils/pbutils-enumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/pbutils/pbutils-enumtypes.h)
// subparse
-//../gst/subparse/gstssaparse.h /epoc32/include/platform/mw/gstreamer/gst/subparse/gstssaparse.h
-//../gst/subparse/gstsubparse.h /epoc32/include/platform/mw/gstreamer/gst/subparse/gstsubparse.h
-//../gst/subparse/samiparse.h /epoc32/include/platform/mw/gstreamer/gst/subparse/samiparse.h
+//../gst/subparse/gstssaparse.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/subparse/gstssaparse.h)
+//../gst/subparse/gstsubparse.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/subparse/gstsubparse.h)
+//../gst/subparse/samiparse.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/subparse/samiparse.h)
// tcp
-//../gst/tcp/gstmultifdsink.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gstmultifdsink.h
-//../gst/tcp/gsttcp-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcp-enumtypes.h
-//../gst/tcp/gsttcp-marshal.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcp-marshal.h
-//../gst/tcp/gsttcp.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcp.h
-//../gst/tcp/gsttcpclientsink.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcpclientsink.h
-//../gst/tcp/gsttcpclientsrc.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcpclientsrc.h
-//../gst/tcp/gsttcpplugin.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcpplugin.h
-//../gst/tcp/gsttcpserversink.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcpserversink.h
-//../gst/tcp/gsttcpserversrc.h /epoc32/include/platform/mw/gstreamer/gst/tcp/gsttcpserversrc.h
+//../gst/tcp/gstmultifdsink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gstmultifdsink.h)
+//../gst/tcp/gsttcp-enumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcp-enumtypes.h)
+//../gst/tcp/gsttcp-marshal.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcp-marshal.h)
+//../gst/tcp/gsttcp.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcp.h)
+//../gst/tcp/gsttcpclientsink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcpclientsink.h)
+//../gst/tcp/gsttcpclientsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcpclientsrc.h)
+//../gst/tcp/gsttcpplugin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcpplugin.h)
+//../gst/tcp/gsttcpserversink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcpserversink.h)
+//../gst/tcp/gsttcpserversrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/tcp/gsttcpserversrc.h)
// videorate
-//../gst/videorate/gstvideorate.h /epoc32/include/platform/mw/gstreamer/gst/videorate/gstvideorate.h
+//../gst/videorate/gstvideorate.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videorate/gstvideorate.h)
// videoscale
-//../gst/videoscale/gstvideoscale.h /epoc32/include/platform/mw/gstreamer/gst/videoscale/gstvideoscale.h
-//../gst/videoscale/vs_image.h /epoc32/include/platform/mw/gstreamer/gst/videoscale/vs_image.h
-//../gst/videoscale/vs_scanline.h /epoc32/include/platform/mw/gstreamer/gst/videoscale/vs_scanline.h
+//../gst/videoscale/gstvideoscale.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videoscale/gstvideoscale.h)
+//../gst/videoscale/vs_image.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videoscale/vs_image.h)
+//../gst/videoscale/vs_scanline.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videoscale/vs_scanline.h)
// videotestsrc
-//../gst/videotestsrc/gstvideotestsrc.h /epoc32/include/platform/mw/gstreamer/gst/videotestsrc/gstvideotestsrc.h
-//../gst/videotestsrc/videotestsrc.h /epoc32/include/platform/mw/gstreamer/gst/videotestsrc/videotestsrc.h
+//../gst/videotestsrc/gstvideotestsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videotestsrc/gstvideotestsrc.h)
+//../gst/videotestsrc/videotestsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/videotestsrc/videotestsrc.h)
// volume
-//../gst/volume/gstvolume.h /epoc32/include/platform/mw/gstreamer/gst/volume/gstvolume.h
+//../gst/volume/gstvolume.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/volume/gstvolume.h)
//liboil - Since liboil port is available, No need to use liboil stub.
-//../gst/oil/liboil.h /epoc32/include/platform/mw/gstreamer/gst/liboil.h
+//../gst/oil/liboil.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/liboil.h)
// fft
-//../gst-libs/gst/fft/_kiss_fft_guts_f32.h /epoc32/include/platform/mw/gstreamer/gst/fft/_kiss_fft_guts_f32.h
-//../gst-libs/gst/fft/_kiss_fft_guts_f64.h /epoc32/include/platform/mw/gstreamer/gst/fft/_kiss_fft_guts_f64.h
-//../gst-libs/gst/fft/_kiss_fft_guts_s16.h /epoc32/include/platform/mw/gstreamer/gst/fft/_kiss_fft_guts_s16.h
-//../gst-libs/gst/fft/_kiss_fft_guts_s32.h /epoc32/include/platform/mw/gstreamer/gst/fft/_kiss_fft_guts_s32.h
-../gst-libs/gst/fft/gstfft.h /epoc32/include/platform/mw/gstreamer/gst/fft/gstfft.h
-../gst-libs/gst/fft/gstfftf32.h /epoc32/include/platform/mw/gstreamer/gst/fft/gstfftf32.h
-../gst-libs/gst/fft/gstfftf64.h /epoc32/include/platform/mw/gstreamer/gst/fft/gstfftf64.h
-../gst-libs/gst/fft/gstffts16.h /epoc32/include/platform/mw/gstreamer/gst/fft/gstffts16.h
-../gst-libs/gst/fft/gstffts32.h /epoc32/include/platform/mw/gstreamer/gst/fft/gstffts32.h
-//../gst-libs/gst/fft/kiss_fft_f32.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fft_f32.h
-//../gst-libs/gst/fft/kiss_fft_f64.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fft_f64.h
-//../gst-libs/gst/fft/kiss_fft_s16.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fft_s16.h
-//../gst-libs/gst/fft/kiss_fft_s32.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fft_s32.h
-//../gst-libs/gst/fft/kiss_fftr_f32.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fftr_f32.h
-//../gst-libs/gst/fft/kiss_fftr_f64.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fftr_f64.h
-//../gst-libs/gst/fft/kiss_fftr_s16.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fftr_s16.h
-//../gst-libs/gst/fft/kiss_fftr_s32.h /epoc32/include/platform/mw/gstreamer/gst/fft/kiss_fftr_s32.h
+//../gst-libs/gst/fft/_kiss_fft_guts_f32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/_kiss_fft_guts_f32.h)
+//../gst-libs/gst/fft/_kiss_fft_guts_f64.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/_kiss_fft_guts_f64.h)
+//../gst-libs/gst/fft/_kiss_fft_guts_s16.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/_kiss_fft_guts_s16.h)
+//../gst-libs/gst/fft/_kiss_fft_guts_s32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/_kiss_fft_guts_s32.h)
+../gst-libs/gst/fft/gstfft.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/gstfft.h)
+../gst-libs/gst/fft/gstfftf32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/gstfftf32.h)
+../gst-libs/gst/fft/gstfftf64.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/gstfftf64.h)
+../gst-libs/gst/fft/gstffts16.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/gstffts16.h)
+../gst-libs/gst/fft/gstffts32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/gstffts32.h)
+//../gst-libs/gst/fft/kiss_fft_f32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fft_f32.h)
+//../gst-libs/gst/fft/kiss_fft_f64.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fft_f64.h)
+//../gst-libs/gst/fft/kiss_fft_s16.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fft_s16.h)
+//../gst-libs/gst/fft/kiss_fft_s32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fft_s32.h)
+//../gst-libs/gst/fft/kiss_fftr_f32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fftr_f32.h)
+//../gst-libs/gst/fft/kiss_fftr_f64.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fftr_f64.h)
+//../gst-libs/gst/fft/kiss_fftr_s16.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fftr_s16.h)
+//../gst-libs/gst/fft/kiss_fftr_s32.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/fft/kiss_fftr_s32.h)
//internationalization macros
-//../gst-libs/gst/gst-i18n-plugin.h /epoc32/include/platform/mw/gstreamer/gst/gst-i18n-plugin.h
+//../gst-libs/gst/gst-i18n-plugin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gst-i18n-plugin.h)
//avcodec
-//../gst/ffmpegcolorspace/avcodec.h /epoc32/include/platform/mw/gstreamer/gst/avcodec.h
+//../gst/ffmpegcolorspace/avcodec.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/avcodec.h)
PRJ_MMPFILES
--- a/gst_plugins_base/gst/oil/liboil.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#ifndef __LIBOIL__
-#define __LIBOIL__
-
-#include<stdint.h>
-#include <stdio.h>
-
-IMPORT_C void resample_linear_u8_ref (uint8_t *dest, uint8_t *src, int n, uint32_t *in);
-IMPORT_C void resample_linear_argb_ref (uint32_t *d, uint32_t *s, int n, uint32_t *in);
-IMPORT_C void merge_linear_argb_ref (uint32_t *d, uint32_t *s1, uint32_t *s2, uint32_t *src3, int n);
-//IMPORT_C void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n);
-IMPORT_C void oil_scalarmultiply_f32_ns (float * d, const float * s1, const float * s2_1, int n);
-IMPORT_C void oil_merge_linear_argb (uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n);
-IMPORT_C void oil_merge_linear_u8 (uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n);
-IMPORT_C void oil_resample_linear_argb (uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2);
-IMPORT_C void oil_resample_linear_u8 (uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2);
-IMPORT_C void oil_splat_u8 (uint8_t * dest, int dstr, const uint8_t * s1_1, int n);
-IMPORT_C void oil_splat_u8_ns (uint8_t * dest, const uint8_t * s1_1, int n);
-
-#endif
--- a/gst_plugins_base/gst/oil/stub.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,501 +0,0 @@
-#include"liboil.h"
-
-//Arun's changes
-typedef struct _OilFunctionImpl OilFunctionImpl;
-typedef struct _OilFunctionClass OilFunctionClass;
-typedef void (*OilTestFunction) (OilFunctionClass *klass,OilFunctionImpl *impl);
-
-#define OIL_CHECK_PROTOTYPE(a)
-/**
- * OilFunctionClass:
- *
- * An opaque structure representing a function class.
- *
- */
-struct _OilFunctionClass {
- /*< private >*/
- void *func;
- const char *name;
- const char *desc;
- OilTestFunction test_func;
-
- OilFunctionImpl *first_impl;
- OilFunctionImpl *reference_impl;
-
- OilFunctionImpl *chosen_impl;
-
- const char *prototype;
-};
-
-
-/**
- * OilFunctionImpl:
- *
- * An opaque structure representing a function implementation.
- *
- */
-struct _OilFunctionImpl {
- /*< private >*/
- void *next;
- OilFunctionClass *klass;
- void *func;
- unsigned int flags;
- const char *name;
- double profile_ave;
- double profile_std;
-};
-
-#ifndef OIL_NO_CLASSES
-/**
- * OIL_DEFINE_CLASS_FULL:
- * @klass: name of class to declare (without oil_ prefix)
- * @string: prototype of class
- * @test: test function
- *
- * Defines a #OilFunctionClass structure for @klass. Classes
- * defined this way will be automatically at Liboil initialization
- * time.
- */
-
-#define OIL_DEFINE_CLASS_FULL(klass, string, test) \
-OilFunctionClass _oil_function_class_ ## klass = { \
- NULL, \
- #klass , \
- NULL, \
- test, \
- NULL, \
- NULL, \
- NULL, \
- string \
-}; \
-OilFunctionClass *oil_function_class_ptr_ ## klass = \
- &_oil_function_class_ ## klass
-#else
-#define OIL_DEFINE_CLASS_FULL(klass, string, test) \
- OIL_DECLARE_CLASS(klass)
-#endif
-
-/**
- * OIL_DEFINE_CLASS:
- * @klass: name of class to declare (without oil_ prefix)
- * @string: prototype of class
- *
- * Defines a #OilFunctionClass structure for @klass. Classes
- * defined this way will be automatically at Liboil initialization
- * time.
- */
-#define OIL_DEFINE_CLASS(klass, string) \
- OIL_DEFINE_CLASS_FULL (klass, string, NULL)
-
-
-OIL_DEFINE_CLASS (scalarmultiply_f32_ns, "float *d, float *s1, float *s2_1, int n");
-
-OIL_DEFINE_CLASS_FULL (resample_linear_argb,
- "uint32_t *d_n, uint32_t *s_2xn, int n, uint32_t *i_2",
- NULL);
-
-OIL_DEFINE_CLASS_FULL (resample_linear_u8,
- "uint8_t *d_n, uint8_t *s_2xn, int n, uint32_t *i_2",
- NULL);
-
-OIL_DEFINE_CLASS_FULL (merge_linear_argb,
- "uint32_t *d_n, uint32_t *s_n, uint32_t *s2_n, uint32_t *s3_1, int n",
- NULL);
-OIL_DEFINE_CLASS_FULL (merge_linear_u8,
- "uint8_t *d_n, uint8_t *s_n, uint8_t *s2_n, uint32_t *s3_1, int n",
- NULL);
-
-OIL_DEFINE_CLASS(splat_u8_ns,"uint8_t *dest, uint8_t *s1_1, int n");
-
-OIL_DEFINE_CLASS(splat_u8,"uint8_t *dest, int dstr, uint8_t *s1_1, int n");
-
-typedef enum {
- OIL_IMPL_FLAG_REF = (1<<0),
- OIL_IMPL_FLAG_OPT = (1<<1),
- OIL_IMPL_FLAG_ASM = (1<<2),
- OIL_IMPL_FLAG_DISABLED = (1<<3),
- OIL_IMPL_FLAG_CMOV = (1<<16),
- OIL_IMPL_FLAG_MMX = (1<<17),
- OIL_IMPL_FLAG_SSE = (1<<18),
- OIL_IMPL_FLAG_MMXEXT = (1<<19),
- OIL_IMPL_FLAG_SSE2 = (1<<20),
- OIL_IMPL_FLAG_3DNOW = (1<<21),
- OIL_IMPL_FLAG_3DNOWEXT = (1<<22),
- OIL_IMPL_FLAG_SSE3 = (1<<23),
- OIL_IMPL_FLAG_ALTIVEC = (1<<24),
- OIL_IMPL_FLAG_EDSP = (1<<25),
- OIL_IMPL_FLAG_ARM6 = (1<<26),
- OIL_IMPL_FLAG_VFP = (1<<27),
- OIL_IMPL_FLAG_SSSE3 = (1<<28)
-} OilImplFlag;
-
-#ifndef OIL_OPT_MANGLE
-#define OIL_OPT_MANGLE(a) a
-#define OIL_OPT_FLAG_MANGLE(a) a
-#else
-#define OIL_NO_CLASSES
-#define OIL_OPT_FLAG_MANGLE(a) (((a)&(~OIL_IMPL_FLAG_REF)) | OIL_IMPL_FLAG_OPT)
-#endif
-#ifndef OIL_OPT_SUFFIX
-#define OIL_OPT_SUFFIX
-#endif
-
-/**
- * OIL_DEFINE_IMPL_FULL:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- * @flags: implementation flags and CPU requirements
- *
- * Defines a #OilFunctionImpl structure for the function @function
- * and class @klass. CPU-dependent flags in @flags will indicate
- * that this implementation requires the given CPU flags.
- */
-#define OIL_DEFINE_IMPL_FULL(function,klass,flags) \
-OilFunctionImpl OIL_OPT_MANGLE(_oil_function_impl_ ## function) = { \
- NULL, \
- &_oil_function_class_ ## klass , \
- (void *)function, \
- OIL_OPT_FLAG_MANGLE(flags), \
- #function OIL_OPT_SUFFIX \
-} \
-OIL_CHECK_PROTOTYPE(;_oil_type_ ## klass _ignore_me_ ## function = function)
-
-/**
- * OIL_DEFINE_IMPL:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- *
- * Shorthand for defining a C implementation. See OIL_DEFINE_IMPL_FULL().
- */
-#define OIL_DEFINE_IMPL(function,klass) \
- OIL_DEFINE_IMPL_FULL(function,klass,0)
-/**
- * OIL_DEFINE_IMPL_REF:
- * @function: name of function
- * @klass: name of class to declare (without oil_ prefix)
- *
- * Shorthand for defining a reference implementation. See OIL_DEFINE_IMPL_FULL().
- */
-#define OIL_DEFINE_IMPL_REF(function,klass) \
- OIL_DEFINE_IMPL_FULL(function,klass,OIL_IMPL_FLAG_REF)
-
-
-
-
-typedef void (*_oil_type_scalarmultiply_f32_ns)(float * d, const float * s1, const float * s2_1, int n);
-//#define oil_scalarmultiply_f32_ns ((_oil_type_scalarmultiply_f32_ns)(*(void **)oil_function_class_ptr_scalarmultiply_f32_ns))
-
-
-
-#define OIL_GET(ptr, offset, type) (*(type *)((uint8_t *)(ptr) + (offset)) )
-
-/**************'_oil_resample_linear_u8'****************************/
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
-static void
-resample_linear_u8_ref (uint8_t *dest, uint8_t *src, int n,
- uint32_t *in)
-{
- int acc = in[0];
- int increment = in[1];
- int i;
- int j;
- int x;
-
- for(i=0;i<n;i++){
- j = acc>>16;
- x = (acc&0xffff)>>8;
- dest[i] = (src[j]*(256-x) + src[j+1]*x) >> 8;
-
- acc += increment;
- }
-
- in[0] = acc;
-}
-
-/************************'_oil_resample_linear_argb'***************************/
-static void
-resample_linear_argb_ref (uint32_t *d, uint32_t *s, int n, uint32_t *in)
-{
- uint8_t *src = (uint8_t *)s;
- uint8_t *dest = (uint8_t *)d;
- int acc = in[0];
- int increment = in[1];
- int i;
- int j;
- int x;
-
- for(i=0;i<n;i++){
- j = acc>>16;
- x = (acc&0xffff)>>8;
- dest[4*i+0] = (src[4*j+0]*(256-x) + src[4*j+4]*x) >> 8;
- dest[4*i+1] = (src[4*j+1]*(256-x) + src[4*j+5]*x) >> 8;
- dest[4*i+2] = (src[4*j+2]*(256-x) + src[4*j+6]*x) >> 8;
- dest[4*i+3] = (src[4*j+3]*(256-x) + src[4*j+7]*x) >> 8;
-
- acc += increment;
- }
-
- in[0] = acc;
-}
-
-/****************** '_oil_merge_linear_argb'**************************/
-static void
-merge_linear_argb_ref (uint32_t *d, uint32_t *s1, uint32_t *s2,
- uint32_t *src3, int n)
-{
- uint8_t *src1 = (uint8_t *)s1;
- uint8_t *src2 = (uint8_t *)s2;
- uint8_t *dest = (uint8_t *)d;
- int i;
- int x = src3[0];
-
- for(i=0;i<n;i++){
- dest[4*i+0] = (src1[4*i+0]*(256-x) + src2[4*i+0]*x) >> 8;
- dest[4*i+1] = (src1[4*i+1]*(256-x) + src2[4*i+1]*x) >> 8;
- dest[4*i+2] = (src1[4*i+2]*(256-x) + src2[4*i+2]*x) >> 8;
- dest[4*i+3] = (src1[4*i+3]*(256-x) + src2[4*i+3]*x) >> 8;
- }
-}
-
-static void
-merge_linear_u8_ref (uint8_t *dest, uint8_t *src1, uint8_t *src2,
- uint32_t *src3, int n)
-{
- int i;
- int x = src3[0];
-
- for(i=0;i<n;i++){
- dest[i] = (src1[i]*(256-x) + src2[i]*x) >> 8;
- }
-}
-
-static void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n)
-{
- int i;
- for(i=0;i<n;i++){
- OIL_GET(dest,i*dstr, uint8_t) = *param;
- }
-}
-
-static void splat_u8_ns_ref (uint8_t *dest, uint8_t *param, int n)
-{
- int i;
- for(i=0;i<n;i++){
- dest[i] = *param;
- }
-}
-
-static void
-scalarmultiply_f32_ns_ref (float *dest, float *src1, float *src2, int n)
-{
- int i;
-
- for(i=0;i<n;i++){
- dest[i] = src1[i] * src2[0];
- }
-}
-
-/********oil_splat_u8*******/
-/*
-EXPORT_C void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n)
-{
- int i;
- for(i=0;i<n;i++){
- OIL_GET(dest,i*dstr, uint8_t) = *param;
- }
-}
-*/
-
-unsigned long oil_cpu_flags;
-
-/**
- * oil_cpu_get_flags:
- *
- * Returns a bitmask containing the available CPU features.
- *
- * Returns: the CPU features.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-unsigned int
-oil_cpu_get_flags (void)
-{
- return oil_cpu_flags;
-}
-
-/**
- * OIL_CPU_FLAG_MASK:
- *
- * Mask describing which bits in #OilImplFlag depend on the current
- * CPU.
- */
-#define OIL_CPU_FLAG_MASK 0xffff0000
-
-/**
- * oil_impl_is_runnable:
- * @impl: an @OilFunctionImpl
- *
- * Determines whether the function implementation given by @impl
- * can be executed by the current CPU.
- *
- * Returns: 1 if the implementation can be executed, otherwise 0
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-int
-oil_impl_is_runnable (OilFunctionImpl *impl)
-{
- unsigned int oil_cpu_flags = oil_cpu_get_flags();
-
- if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
- return 0;
- return 1;
-}
-
-/**
- * oil_class_optimize:
- * @klass: a function class
- *
- * Tests and profiles each implementation for the given function
- * class. Testing compares the output of running each implementation
- * on random input against the reference implementation for the
- * same input.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-oil_class_optimize (OilFunctionClass * klass)
-{
- OilFunctionImpl *impl;
- OilFunctionImpl *min_impl;
- int ret;
-
-
- if (klass->reference_impl == NULL) {
- return;
- }
- if (klass->first_impl == NULL) {
- return;
- }
-
- min_impl = NULL;
-
- for (impl = klass->first_impl; impl; impl = impl->next) {
- if (!oil_impl_is_runnable (impl))
- continue;
- }
-
- if (min_impl == NULL) {
- return;
- }
-
- klass->chosen_impl = min_impl;
- klass->func = min_impl->func;
-
-}
-
-
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void oil_scalarmultiply_f32_ns (float * d, const float * s1, const float * s2_1, int n)
-{
- /*
- if (_oil_function_class_scalarmultiply_f32_ns.func == NULL) {
- oil_class_optimize (&_oil_function_class_scalarmultiply_f32_ns);
- }
- */
- scalarmultiply_f32_ns_ref(d,(float*) s1,(float*) s2_1, n);
- //((void (*)(float * d, const float * s1, const float * s2_1, int n))(_oil_function_class_scalarmultiply_f32_ns.func))(d, s1, s2_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
- void
-oil_merge_linear_argb (uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n)
-{
- if (_oil_function_class_merge_linear_argb.func == NULL) {
- oil_class_optimize (&_oil_function_class_merge_linear_argb);
- }
- ((void (*)(uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_argb.func))(d_n, s_n, s2_n, s3_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void
-oil_merge_linear_u8 (uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n)
-{
- if (_oil_function_class_merge_linear_u8.func == NULL) {
- oil_class_optimize (&_oil_function_class_merge_linear_u8);
- }
- ((void (*)(uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_u8.func))(d_n, s_n, s2_n, s3_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
- void
-oil_resample_linear_argb (uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2)
-{
- if (_oil_function_class_resample_linear_argb.func == NULL) {
- oil_class_optimize (&_oil_function_class_resample_linear_argb);
- }
- ((void (*)(uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_argb.func))(d_n, s_2xn, n, i_2);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
- void
-oil_resample_linear_u8 (uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2)
-{
- if (_oil_function_class_resample_linear_u8.func == NULL) {
- oil_class_optimize (&_oil_function_class_resample_linear_u8);
- }
- ((void (*)(uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_u8.func))(d_n, s_2xn, n, i_2);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-
- void
-oil_splat_u8 (uint8_t * dest, int dstr, const uint8_t * s1_1, int n)
-{
- if (_oil_function_class_splat_u8.func == NULL) {
- oil_class_optimize (&_oil_function_class_splat_u8);
- }
- ((void (*)(uint8_t * dest, int dstr, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8.func))(dest, dstr, s1_1, n);
-}
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-oil_splat_u8_ns (uint8_t * dest, const uint8_t * s1_1, int n)
-{
- if (_oil_function_class_splat_u8_ns.func == NULL) {
- oil_class_optimize (&_oil_function_class_splat_u8_ns);
- }
- ((void (*)(uint8_t * dest, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8_ns.func))(dest, s1_1, n);
-}
-
-OIL_DEFINE_IMPL_REF (scalarmultiply_f32_ns_ref, scalarmultiply_f32_ns);
-OIL_DEFINE_IMPL_REF (resample_linear_u8_ref, resample_linear_u8);
-OIL_DEFINE_IMPL_REF (resample_linear_argb_ref, resample_linear_argb);
-OIL_DEFINE_IMPL_REF (merge_linear_argb_ref, merge_linear_argb);
-OIL_DEFINE_IMPL_REF (merge_linear_u8_ref, merge_linear_u8);
-OIL_DEFINE_IMPL_REF(splat_u8_ref, splat_u8);
-OIL_DEFINE_IMPL_REF(splat_u8_ns_ref, splat_u8_ns);
-
--- a/gst_plugins_base/sys/v4l/gstv4l.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* GStreamer
- *
- * gstv4l.c: plugin for v4l elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst/gst-i18n-plugin.h"
-
-#include <gst/gst.h>
-
-#include "gstv4lelement.h"
-#include "gstv4lsrc.h"
-/* #include "gstv4ljpegsrc.h" */
-/* #include "gstv4lmjpegsrc.h" */
-/* #include "gstv4lmjpegsink.h" */
-
-GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls");
-
- if (!gst_element_register (plugin, "v4lsrc", GST_RANK_NONE, GST_TYPE_V4LSRC))
-/* !gst_element_register (plugin, "v4ljpegsrc", */
-/* GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) || */
-/* !gst_element_register (plugin, "v4lmjpegsrc", */
-/* GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) || */
-/* !gst_element_register (plugin, "v4lmjpegsink", */
-/* GST_RANK_NONE, GST_TYPE_V4LMJPEGSINK)) */
- return FALSE;
-
-#ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-#endif /* ENABLE_NLS */
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "video4linux",
- "elements for Video 4 Linux",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/v4l/gstv4lcolorbalance.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/* GStreamer
- *
- * gstv4lcolorbalance.c: color balance interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-#include "gstv4lcolorbalance.h"
-#include "gstv4lelement.h"
-
-static void
-gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass *
- klass);
-static void gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel *
- channel);
-
-static const GList *gst_v4l_color_balance_list_channels (GstColorBalance *
- balance);
-static void gst_v4l_color_balance_set_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel, gint value);
-static gint gst_v4l_color_balance_get_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel);
-
-static GstColorBalanceChannelClass *parent_class = NULL;
-
-GType
-gst_v4l_color_balance_channel_get_type (void)
-{
- static GType gst_v4l_color_balance_channel_type = 0;
-
- if (!gst_v4l_color_balance_channel_type) {
- static const GTypeInfo v4l_tuner_channel_info = {
- sizeof (GstV4lColorBalanceChannelClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_v4l_color_balance_channel_class_init,
- NULL,
- NULL,
- sizeof (GstV4lColorBalanceChannel),
- 0,
- (GInstanceInitFunc) gst_v4l_color_balance_channel_init,
- NULL
- };
-
- gst_v4l_color_balance_channel_type =
- g_type_register_static (GST_TYPE_COLOR_BALANCE_CHANNEL,
- "GstV4lColorBalanceChannel", &v4l_tuner_channel_info, 0);
- }
-
- return gst_v4l_color_balance_channel_type;
-}
-
-static void
-gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass *
- klass)
-{
- parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel * channel)
-{
- channel->index = 0;
-}
-
-void
-gst_v4l_color_balance_interface_init (GstColorBalanceClass * klass)
-{
- GST_COLOR_BALANCE_TYPE (klass) = GST_COLOR_BALANCE_HARDWARE;
-
- /* default virtual functions */
- klass->list_channels = gst_v4l_color_balance_list_channels;
- klass->set_value = gst_v4l_color_balance_set_value;
- klass->get_value = gst_v4l_color_balance_get_value;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_color_balance_contains_channel (GstV4lElement * v4lelement,
- GstV4lColorBalanceChannel * v4lchannel)
-{
- const GList *item;
-
- for (item = v4lelement->colors; item != NULL; item = item->next)
- if (item->data == v4lchannel)
- return TRUE;
-
- return FALSE;
-}
-
-static const GList *
-gst_v4l_color_balance_list_channels (GstColorBalance * balance)
-{
- return GST_V4LELEMENT (balance)->colors;
-}
-
-static void
-gst_v4l_color_balance_set_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel, gint value)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (balance);
- GstV4lColorBalanceChannel *v4lchannel =
- GST_V4L_COLOR_BALANCE_CHANNEL (channel);
-
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
- g_return_if_fail (gst_v4l_color_balance_contains_channel (v4lelement,
- v4lchannel));
-
- gst_v4l_set_picture (v4lelement, v4lchannel->index, value);
-}
-
-static gint
-gst_v4l_color_balance_get_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (balance);
- GstV4lColorBalanceChannel *v4lchannel =
- GST_V4L_COLOR_BALANCE_CHANNEL (channel);
- gint value;
-
- /* assert that we're opened and that we're using a known item */
- g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
- g_return_val_if_fail (gst_v4l_color_balance_contains_channel (v4lelement,
- v4lchannel), 0);
-
- if (!gst_v4l_get_picture (v4lelement, v4lchannel->index, &value))
- return 0;
-
- return value;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lcolorbalance.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* GStreamer
- *
- * gstv4lcolorbalance.h: color balance interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4L_COLOR_BALANCE_H__
-#define __GST_V4L_COLOR_BALANCE_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/colorbalance.h>
-#include "v4l_calls.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4L_COLOR_BALANCE_CHANNEL \
- (gst_v4l_color_balance_channel_get_type ())
-#define GST_V4L_COLOR_BALANCE_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \
- GstV4lColorBalanceChannel))
-#define GST_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \
- GstV4lColorBalanceChannelClass))
-#define GST_IS_V4L_COLOR_BALANCE_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL))
-#define GST_IS_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL))
-
-typedef struct _GstV4lColorBalanceChannel {
- GstColorBalanceChannel parent;
-
- GstV4lPictureType index;
-} GstV4lColorBalanceChannel;
-
-typedef struct _GstV4lColorBalanceChannelClass {
- GstColorBalanceChannelClass parent;
-} GstV4lColorBalanceChannelClass;
-
-GType gst_v4l_color_balance_channel_get_type (void);
-
-void gst_v4l_color_balance_interface_init (GstColorBalanceClass *klass);
-
-#endif /* __GST_V4L_COLOR_BALANCE_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lelement.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,470 +0,0 @@
-/* GStreamer
- *
- * gstv4lelement.c: base class for V4L elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <gst/interfaces/propertyprobe.h>
-
-#include "v4l_calls.h"
-#include "gstv4ltuner.h"
-#ifdef HAVE_XVIDEO
-#include "gstv4lxoverlay.h"
-#endif
-#include "gstv4lcolorbalance.h"
-
-
-enum
-{
- PROP_0,
- PROP_DEVICE,
- PROP_DEVICE_NAME,
- PROP_FLAGS
-};
-
-
-static void gst_v4lelement_init_interfaces (GType type);
-
-GST_BOILERPLATE_FULL (GstV4lElement, gst_v4lelement, GstPushSrc,
- GST_TYPE_PUSH_SRC, gst_v4lelement_init_interfaces);
-
-
-static void gst_v4lelement_dispose (GObject * object);
-static void gst_v4lelement_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4lelement_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-static gboolean gst_v4lelement_start (GstBaseSrc * src);
-static gboolean gst_v4lelement_stop (GstBaseSrc * src);
-
-
-static gboolean
-gst_v4l_iface_supported (GstImplementsInterface * iface, GType iface_type)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (iface);
-
-#ifdef HAVE_XVIDEO
- g_assert (iface_type == GST_TYPE_TUNER ||
- iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_COLOR_BALANCE);
-#else
- g_assert (iface_type == GST_TYPE_TUNER ||
- iface_type == GST_TYPE_COLOR_BALANCE);
-#endif
-
- if (v4lelement->video_fd == -1)
- return FALSE;
-
-#ifdef HAVE_XVIDEO
- if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L_IS_OVERLAY (v4lelement))
- return FALSE;
-#endif
-
- return TRUE;
-}
-
-static void
-gst_v4l_interface_init (GstImplementsInterfaceClass * klass)
-{
- /* default virtual functions */
- klass->supported = gst_v4l_iface_supported;
-}
-
-static const GList *
-gst_v4l_probe_get_properties (GstPropertyProbe * probe)
-{
- GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
- static GList *list = NULL;
-
- if (!list) {
- list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
- }
-
- return list;
-}
-
-static gboolean
-gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check)
-{
- static gboolean init = FALSE;
- static GList *devices = NULL;
-
- if (!init && !check) {
- gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL };
- gint base, n, fd;
-
- while (devices) {
- GList *item = devices;
- gchar *device = item->data;
-
- devices = g_list_remove (devices, item);
- g_free (device);
- }
-
- /* detect /dev entries */
- for (n = 0; n < 64; n++) {
- for (base = 0; dev_base[base] != NULL; base++) {
- struct stat s;
- gchar *device = g_strdup_printf ("%s%d", dev_base[base], n);
-
- /* does the /dev/ entry exist at all? */
- if (stat (device, &s) == 0) {
- /* yes: is a device attached? */
- if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) {
- if (fd > 0)
- close (fd);
-
- devices = g_list_append (devices, device);
- break;
- }
- }
- g_free (device);
- }
- }
-
- init = TRUE;
- }
-
- klass->devices = devices;
-
- return init;
-}
-
-static void
-gst_v4l_probe_probe_property (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
-
- switch (prop_id) {
- case PROP_DEVICE:
- gst_v4l_class_probe_devices (klass, FALSE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_v4l_probe_needs_probe (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
- gboolean ret = FALSE;
-
- switch (prop_id) {
- case PROP_DEVICE:
- ret = !gst_v4l_class_probe_devices (klass, TRUE);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return ret;
-}
-
-static GValueArray *
-gst_v4l_class_list_devices (GstV4lElementClass * klass)
-{
- GValueArray *array;
- GValue value = { 0 };
- GList *item;
-
- if (!klass->devices)
- return NULL;
-
- array = g_value_array_new (g_list_length (klass->devices));
- item = klass->devices;
- g_value_init (&value, G_TYPE_STRING);
- while (item) {
- gchar *device = item->data;
-
- g_value_set_string (&value, device);
- g_value_array_append (array, &value);
-
- item = item->next;
- }
- g_value_unset (&value);
-
- return array;
-}
-
-static GValueArray *
-gst_v4l_probe_get_values (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe);
- GValueArray *array = NULL;
-
- switch (prop_id) {
- case PROP_DEVICE:
- array = gst_v4l_class_list_devices (klass);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return array;
-}
-
-static void
-gst_v4l_property_probe_interface_init (GstPropertyProbeInterface * iface)
-{
- iface->get_properties = gst_v4l_probe_get_properties;
- iface->probe_property = gst_v4l_probe_probe_property;
- iface->needs_probe = gst_v4l_probe_needs_probe;
- iface->get_values = gst_v4l_probe_get_values;
-}
-
-#define GST_TYPE_V4L_DEVICE_FLAGS (gst_v4l_device_get_type ())
-static GType
-gst_v4l_device_get_type (void)
-{
- static GType v4l_device_type = 0;
-
- if (v4l_device_type == 0) {
- static const GFlagsValue values[] = {
- {VID_TYPE_CAPTURE, "CAPTURE", "Device can capture"},
- {VID_TYPE_TUNER, "TUNER", "Device has a tuner"},
- {VID_TYPE_OVERLAY, "OVERLAY", "Device can do overlay"},
- {VID_TYPE_MPEG_DECODER, "MPEG_DECODER", "Device can decode MPEG"},
- {VID_TYPE_MPEG_ENCODER, "MPEG_ENCODER", "Device can encode MPEG"},
- {VID_TYPE_MJPEG_DECODER, "MJPEG_DECODER", "Device can decode MJPEG"},
- {VID_TYPE_MJPEG_ENCODER, "MJPEG_ENCODER", "Device can encode MJPEG"},
- {0x10000, "AUDIO", "Device handles audio"},
- {0, NULL, NULL}
- };
-
- v4l_device_type = g_flags_register_static ("GstV4lDeviceTypeFlags", values);
- }
-
- return v4l_device_type;
-}
-
-static void
-gst_v4lelement_init_interfaces (GType type)
-{
- static const GInterfaceInfo v4liface_info = {
- (GInterfaceInitFunc) gst_v4l_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo v4l_tuner_info = {
- (GInterfaceInitFunc) gst_v4l_tuner_interface_init,
- NULL,
- NULL,
- };
-#ifdef HAVE_XVIDEO
- static const GInterfaceInfo v4l_xoverlay_info = {
- (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init,
- NULL,
- NULL,
- };
-#endif
- static const GInterfaceInfo v4l_colorbalance_info = {
- (GInterfaceInitFunc) gst_v4l_color_balance_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo v4l_propertyprobe_info = {
- (GInterfaceInitFunc) gst_v4l_property_probe_interface_init,
- NULL,
- NULL,
- };
-
- g_type_add_interface_static (type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info);
- g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l_tuner_info);
-#ifdef HAVE_XVIDEO
- g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l_xoverlay_info);
-#endif
- g_type_add_interface_static (type,
- GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info);
- g_type_add_interface_static (type,
- GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info);
-}
-
-
-static void
-gst_v4lelement_base_init (gpointer g_class)
-{
- GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class);
-
- klass->devices = NULL;
-}
-
-static void
-gst_v4lelement_class_init (GstV4lElementClass * klass)
-{
- GObjectClass *gobject_class;
- GstBaseSrcClass *basesrc_class;
-
- gobject_class = (GObjectClass *) klass;
- basesrc_class = (GstBaseSrcClass *) klass;
-
- gobject_class->set_property = gst_v4lelement_set_property;
- gobject_class->get_property = gst_v4lelement_get_property;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE,
- g_param_spec_string ("device", "Device", "Device location",
- NULL, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME,
- g_param_spec_string ("device_name", "Device name", "Name of the device",
- NULL, G_PARAM_READABLE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS,
- g_param_spec_flags ("flags", "Flags", "Device type flags",
- GST_TYPE_V4L_DEVICE_FLAGS, 0, G_PARAM_READABLE));
-
- basesrc_class->start = gst_v4lelement_start;
- basesrc_class->stop = gst_v4lelement_stop;
-
- gobject_class->dispose = gst_v4lelement_dispose;
-}
-
-
-static void
-gst_v4lelement_init (GstV4lElement * v4lelement, GstV4lElementClass * klass)
-{
- /* some default values */
- v4lelement->video_fd = -1;
- v4lelement->buffer = NULL;
- v4lelement->videodev = g_strdup ("/dev/video0");
-
- v4lelement->norms = NULL;
- v4lelement->channels = NULL;
- v4lelement->colors = NULL;
-
- v4lelement->xwindow_id = 0;
-}
-
-
-static void
-gst_v4lelement_dispose (GObject * object)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
- if (v4lelement->videodev) {
- g_free (v4lelement->videodev);
- v4lelement->videodev = NULL;
- }
-
- if (((GObjectClass *) parent_class)->dispose)
- ((GObjectClass *) parent_class)->dispose (object);
-}
-
-
-static void
-gst_v4lelement_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- if (v4lelement->videodev)
- g_free (v4lelement->videodev);
- v4lelement->videodev = g_strdup (g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-gst_v4lelement_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (object);
-
- switch (prop_id) {
- case PROP_DEVICE:
- g_value_set_string (value, v4lelement->videodev);
- break;
- case PROP_DEVICE_NAME:{
- gchar *new = NULL;
-
- if (GST_V4L_IS_OPEN (v4lelement)) {
- new = v4lelement->vcap.name;
- } else if (gst_v4l_open (v4lelement)) {
- new = v4lelement->vcap.name;
- gst_v4l_close (v4lelement);
- }
- g_value_set_string (value, new);
- break;
- }
- case PROP_FLAGS:{
- guint flags = 0;
-
- if (GST_V4L_IS_OPEN (v4lelement)) {
- flags |= v4lelement->vcap.type & 0x3C0B;
- if (v4lelement->vcap.audios)
- flags |= 0x10000;
- }
- g_value_set_flags (value, flags);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_v4lelement_start (GstBaseSrc * src)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (src);
-
- if (!gst_v4l_open (v4lelement))
- return FALSE;
-
-#ifdef HAVE_XVIDEO
- gst_v4l_xoverlay_start (v4lelement);
-#endif
-
- return TRUE;
-}
-
-static gboolean
-gst_v4lelement_stop (GstBaseSrc * src)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (src);
-
-#ifdef HAVE_XVIDEO
- gst_v4l_xoverlay_stop (v4lelement);
-#endif
-
- if (!gst_v4l_close (v4lelement))
- return FALSE;
-
- return TRUE;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lelement.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/* GStreamer
- *
- * gstv4lelement.h: base class for V4L elements
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4LELEMENT_H__
-#define __GST_V4LELEMENT_H__
-
-/* Because of some really cool feature in video4linux1, also known as
- * 'not including sys/types.h and sys/time.h', we had to include it
- * ourselves. In all their intelligence, these people decided to fix
- * this in the next version (video4linux2) in such a cool way that it
- * breaks all compilations of old stuff...
- * The real problem is actually that linux/time.h doesn't use proper
- * macro checks before defining types like struct timeval. The proper
- * fix here is to either fuck the kernel header (which is what we do
- * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it
- * upstream, which I'll consider doing later on. If you get compiler
- * errors here, check your linux/time.h && sys/time.h header setup.
- */
-#include <sys/types.h>
-#define _LINUX_TIME_H
-#include <linux/videodev.h>
-
-#include <gst/gst.h>
-#include <gst/base/gstpushsrc.h>
-
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4LELEMENT \
- (gst_v4lelement_get_type())
-#define GST_V4LELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LELEMENT,GstV4lElement))
-#define GST_V4LELEMENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LELEMENT,GstV4lElementClass))
-#define GST_IS_V4LELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LELEMENT))
-#define GST_IS_V4LELEMENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LELEMENT))
-#define GST_V4LELEMENT_GET_CLASS(klass) \
- (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_V4LELEMENT, GstV4lElementClass))
-
-typedef struct _GstV4lElement GstV4lElement;
-typedef struct _GstV4lElementClass GstV4lElementClass;
-typedef struct _GstV4lXv GstV4lXv;
-
-struct _GstV4lElement {
- GstPushSrc element;
-
- /* the video device */
- char *videodev;
-
- /* the video-device's file descriptor */
- gint video_fd;
-
- /* the video buffer (mmap()'ed) */
- guint8 *buffer;
-
- /* the video device's capabilities */
- struct video_capability vcap;
-
- /* the video device's window properties */
- struct video_window vwin;
-
- /* some more info about the current input's capabilities */
- struct video_channel vchan;
-
- /* lists... */
- GList *colors;
- GList *norms;
- GList *channels;
-
- /* X-overlay */
- GstV4lXv *xv;
- gulong xwindow_id;
-};
-
-struct _GstV4lElementClass {
- GstPushSrcClass parent_class;
-
- /* probed devices */
- GList *devices;
-
- /* actions */
- gboolean (*get_attribute) (GstElement *element,
- const gchar *attr_name,
- int *value);
- gboolean (*set_attribute) (GstElement *element,
- const gchar *attr_name,
- const int value);
-};
-
-GType gst_v4lelement_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_V4LELEMENT_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4ljpegsrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/* GStreamer
- *
- * gstv4ljpegsrc.h: V4L video source element for JPEG cameras
- *
- * Copyright (C) 2001-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 __GST_V4LJPEGSRC_H__
-#define __GST_V4LJPEGSRC_H__
-
-#include <gstv4lsrc.h>
-
-G_BEGIN_DECLS
-#define GST_TYPE_V4LJPEGSRC \
- (gst_v4ljpegsrc_get_type())
-#define GST_V4LJPEGSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrc))
-#define GST_V4LJPEGSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrcClass))
-#define GST_IS_V4LJPEGSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LJPEGSRC))
-#define GST_IS_V4LJPEGSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LJPEGSRC))
-typedef struct _GstV4lJpegSrc GstV4lJpegSrc;
-typedef struct _GstV4lJpegSrcClass GstV4lJpegSrcClass;
-
-struct _GstV4lJpegSrc
-{
- GstV4lSrc v4lsrc;
- GstPadGetFunction getfn;
- GstPadGetCapsFunction getcapsfn;
-};
-
-struct _GstV4lJpegSrcClass
-{
- GstV4lSrcClass parent_class;
-};
-
-GType gst_v4ljpegsrc_get_type (void);
-
-G_END_DECLS
-#endif /* __GST_V4LJPEGSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lmjpegsink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* GStreamer
- *
- * gstv4lmjpegsink.h: hardware MJPEG video sink element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4LMJPEGSINK_H__
-#define __GST_V4LMJPEGSINK_H__
-
-#include <gstv4lelement.h>
-#include <sys/time.h>
-#include <videodev_mjpeg.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_V4LMJPEGSINK \
- (gst_v4lmjpegsink_get_type())
-#define GST_V4LMJPEGSINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSink))
-#define GST_V4LMJPEGSINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSinkClass))
-#define GST_IS_V4LMJPEGSINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSINK))
-#define GST_IS_V4LMJPEGSINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSINK))
-
-typedef struct _GstV4lMjpegSink GstV4lMjpegSink;
-typedef struct _GstV4lMjpegSinkClass GstV4lMjpegSinkClass;
-
-struct _GstV4lMjpegSink {
- GstV4lElement v4lelement;
-
- /* the sink pas */
- GstPad *sinkpad;
-
- /* frame properties for common players */
- gint frames_displayed;
- guint64 frame_time;
-
- /* system clock object */
- GstClock *clock;
-
- /* buffer/capture info */
- struct mjpeg_sync bsync;
- struct mjpeg_requestbuffers breq;
-
- /* thread to keep track of synced frames */
- gint8 *isqueued_queued_frames; /* 1 = queued, 0 = unqueued, -1 = error */
- GThread *thread_queued_frames;
- GMutex *mutex_queued_frames;
- GCond **cond_queued_frames;
- gint current_frame;
-
- /* width/height/norm of the jpeg stream */
- gint width;
- gint height;
- gint norm;
-
- /* cache values */
- gint x_offset;
- gint y_offset;
-
- gint numbufs;
- gint bufsize; /* in KB */
-};
-
-struct _GstV4lMjpegSinkClass {
- GstV4lElementClass parent_class;
-
- /* signals */
- void (*frame_displayed) (GstElement *element);
-};
-
-GType gst_v4lmjpegsink_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_SDLVIDEOSINK_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lmjpegsrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/* GStreamer
- *
- * gstv4lmjpegsrc.h: hardware MJPEG video source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4LMJPEGSRC_H__
-#define __GST_V4LMJPEGSRC_H__
-
-#include <gstv4lelement.h>
-#include <sys/time.h>
-#include <videodev_mjpeg.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4LMJPEGSRC \
- (gst_v4lmjpegsrc_get_type())
-#define GST_V4LMJPEGSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrc))
-#define GST_V4LMJPEGSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrcClass))
-#define GST_IS_V4LMJPEGSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSRC))
-#define GST_IS_V4LMJPEGSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSRC))
-
-typedef struct _GstV4lMjpegSrc GstV4lMjpegSrc;
-typedef struct _GstV4lMjpegSrcClass GstV4lMjpegSrcClass;
-
-struct _GstV4lMjpegSrc {
- GstV4lElement v4lelement;
-
- /* pads */
- GstPad *srcpad;
-
- /* buffer/capture info */
- struct mjpeg_sync bsync;
- struct mjpeg_requestbuffers breq;
-
- /* num of queued frames and some GThread stuff
- * to wait if there's not enough */
- gint8 *frame_queue_state;
- GMutex *mutex_queue_state;
- GCond *cond_queue_state;
- gint num_queued;
- gint queue_frame;
-
- /* True if we want to stop */
- gboolean quit, is_capturing;
-
- /* A/V sync... frame counter and internal cache */
- gulong handled;
- gint last_frame;
- gint last_size;
- gint need_writes;
- gulong last_seq;
-
- /* clock */
- GstClock *clock;
-
- /* time to substract from clock time to get back to timestamp */
- GstClockTime substract_time;
-
- /* how often are we going to use each frame? */
- gint *use_num_times;
-
- /* how are we going to push buffers? */
- gboolean use_fixed_fps;
-
- /* end size */
- gint end_width, end_height;
-
- /* caching values */
-#if 0
- gint x_offset;
- gint y_offset;
- gint frame_width;
- gint frame_height;
-#endif
-
- gint quality;
- gint numbufs;
-};
-
-struct _GstV4lMjpegSrcClass {
- GstV4lElementClass parent_class;
-
- void (*frame_capture) (GObject *object);
- void (*frame_drop) (GObject *object);
- void (*frame_insert) (GObject *object);
- void (*frame_lost) (GObject *object,
- gint num_lost);
-};
-
-GType gst_v4lmjpegsrc_get_type(void);
-
-
-G_END_DECLS
-
-#endif /* __GST_V4LMJPEGSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lsrc.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,732 +0,0 @@
-/* GStreamer
- *
- * gstv4lsrc.c: BT8x8/V4L source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <sys/time.h>
-#include "v4lsrc_calls.h"
-#include <sys/ioctl.h>
-
-
-static const GstElementDetails gst_v4lsrc_details =
-GST_ELEMENT_DETAILS ("Video (video4linux/raw) Source",
- "Source/Video",
- "Reads raw frames from a video4linux device",
- "Ronald Bultje <rbultje@ronald.bitfreak.net>");
-
-
-GST_DEBUG_CATEGORY_STATIC (v4lsrc_debug);
-#define GST_CAT_DEFAULT v4lsrc_debug
-
-
-enum
-{
- PROP_0,
- PROP_AUTOPROBE,
- PROP_AUTOPROBE_FPS,
- PROP_COPY_MODE,
- PROP_TIMESTAMP_OFFSET
-};
-
-
-GST_BOILERPLATE (GstV4lSrc, gst_v4lsrc, GstV4lElement, GST_TYPE_V4LELEMENT);
-
-
-/* basesrc methods */
-static gboolean gst_v4lsrc_start (GstBaseSrc * src);
-static gboolean gst_v4lsrc_stop (GstBaseSrc * src);
-static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
-static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
-static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
-static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query);
-static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps);
-
-static void gst_v4lsrc_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_v4lsrc_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-
-static void
-gst_v4lsrc_base_init (gpointer g_class)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (gstelement_class, &gst_v4lsrc_details);
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
- gst_caps_new_any ()));
-}
-
-static void
-gst_v4lsrc_class_init (GstV4lSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstBaseSrcClass *basesrc_class;
- GstPushSrcClass *pushsrc_class;
-
- gobject_class = (GObjectClass *) klass;
- basesrc_class = (GstBaseSrcClass *) klass;
- pushsrc_class = (GstPushSrcClass *) klass;
-
- gobject_class->set_property = gst_v4lsrc_set_property;
- gobject_class->get_property = gst_v4lsrc_get_property;
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE,
- g_param_spec_boolean ("autoprobe", "Autoprobe",
- "Whether the device should be probed for all possible features",
- TRUE, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE_FPS,
- g_param_spec_boolean ("autoprobe-fps", "Autoprobe FPS",
- "Whether the device should be probed for framerates",
- TRUE, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COPY_MODE,
- g_param_spec_boolean ("copy-mode", "Copy mode",
- "Whether to send out copies of buffers, or direct pointers to the mmap region",
- TRUE, G_PARAM_READWRITE));
- g_object_class_install_property (G_OBJECT_CLASS (klass),
- PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset",
- "Timestamp offset",
- "A time offset subtracted from timestamps set on buffers (in ns)",
- G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE));
-
- GST_DEBUG_CATEGORY_INIT (v4lsrc_debug, "v4lsrc", 0, "V4L source element");
-
- basesrc_class->get_caps = gst_v4lsrc_get_caps;
- basesrc_class->set_caps = gst_v4lsrc_set_caps;
- basesrc_class->start = gst_v4lsrc_start;
- basesrc_class->stop = gst_v4lsrc_stop;
- basesrc_class->fixate = gst_v4lsrc_fixate;
- basesrc_class->query = gst_v4lsrc_query;
-
- pushsrc_class->create = gst_v4lsrc_create;
-}
-
-static void
-gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass)
-{
- v4lsrc->buffer_size = 0;
-
- /* no colorspaces */
- v4lsrc->colorspaces = NULL;
-
- v4lsrc->is_capturing = FALSE;
- v4lsrc->autoprobe = TRUE;
- v4lsrc->autoprobe_fps = TRUE;
- v4lsrc->copy_mode = TRUE;
-
- v4lsrc->timestamp_offset = 0;
-
- v4lsrc->fps_list = NULL;
-
- gst_base_src_set_format (GST_BASE_SRC (v4lsrc), GST_FORMAT_TIME);
- gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE);
-}
-
-static void
-gst_v4lsrc_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstV4lSrc *v4lsrc = GST_V4LSRC (object);
-
- switch (prop_id) {
- case PROP_AUTOPROBE:
- g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
- v4lsrc->autoprobe = g_value_get_boolean (value);
- break;
- case PROP_AUTOPROBE_FPS:
- g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)));
- v4lsrc->autoprobe_fps = g_value_get_boolean (value);
- break;
- case PROP_COPY_MODE:
- v4lsrc->copy_mode = g_value_get_boolean (value);
- break;
- case PROP_TIMESTAMP_OFFSET:
- v4lsrc->timestamp_offset = g_value_get_int64 (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-gst_v4lsrc_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstV4lSrc *v4lsrc = GST_V4LSRC (object);
-
- switch (prop_id) {
- case PROP_AUTOPROBE:
- g_value_set_boolean (value, v4lsrc->autoprobe);
- break;
- case PROP_AUTOPROBE_FPS:
- g_value_set_boolean (value, v4lsrc->autoprobe_fps);
- break;
- case PROP_COPY_MODE:
- g_value_set_boolean (value, v4lsrc->copy_mode);
- break;
- case PROP_TIMESTAMP_OFFSET:
- g_value_set_int64 (value, v4lsrc->timestamp_offset);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* this function is a bit of a last resort */
-static void
-gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
-{
- GstStructure *structure;
- int i;
- int targetwidth, targetheight;
- GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc);
- struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
- struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
- if (GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
- GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d",
- vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight);
- targetwidth = vcap->minwidth;
- targetheight = vcap->minheight;
- /* if we can get the current vwin settings, we use those to fixate */
- if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc)))
- GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities");
- else {
- targetwidth = vwin->width;
- targetheight = vwin->height;
- }
- } else {
- GST_DEBUG_OBJECT (v4lsrc, "device closed, guessing");
- targetwidth = 320;
- targetheight = 200;
- }
-
- GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight);
-
- for (i = 0; i < gst_caps_get_size (caps); ++i) {
- const GValue *v;
-
- structure = gst_caps_get_structure (caps, i);
- gst_structure_fixate_field_nearest_int (structure, "width", targetwidth);
- gst_structure_fixate_field_nearest_int (structure, "height", targetheight);
- gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2);
-
- v = gst_structure_get_value (structure, "format");
- if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
- guint32 fourcc;
-
- g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
-
- fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
- gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
- }
- }
-}
-
-static gint all_palettes[] = {
- VIDEO_PALETTE_YUV422,
- VIDEO_PALETTE_YUV420P,
- VIDEO_PALETTE_UYVY,
- VIDEO_PALETTE_YUV411P,
- VIDEO_PALETTE_YUV422P,
- VIDEO_PALETTE_YUV410P,
- VIDEO_PALETTE_YUV411,
- VIDEO_PALETTE_RGB555,
- VIDEO_PALETTE_RGB565,
- VIDEO_PALETTE_RGB24,
- VIDEO_PALETTE_RGB32,
- -1
-};
-
-static GstCaps *
-gst_v4lsrc_palette_to_caps (int palette)
-{
- guint32 fourcc;
- GstCaps *caps;
-
- switch (palette) {
- case VIDEO_PALETTE_YUV422:
- case VIDEO_PALETTE_YUYV:
- fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
- break;
- case VIDEO_PALETTE_YUV420P:
- fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
- break;
- case VIDEO_PALETTE_UYVY:
- fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
- break;
- case VIDEO_PALETTE_YUV411P:
- fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
- break;
- case VIDEO_PALETTE_YUV411:
- fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
- break;
- case VIDEO_PALETTE_YUV422P:
- fourcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
- break;
- case VIDEO_PALETTE_YUV410P:
- fourcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
- break;
- case VIDEO_PALETTE_RGB555:
- case VIDEO_PALETTE_RGB565:
- case VIDEO_PALETTE_RGB24:
- case VIDEO_PALETTE_RGB32:
- fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
- break;
- default:
- return NULL;
- }
-
- if (fourcc == GST_MAKE_FOURCC ('R', 'G', 'B', ' ')) {
- switch (palette) {
- case VIDEO_PALETTE_RGB555:
- caps = gst_caps_from_string ("video/x-raw-rgb, "
- "bpp = (int) 16, "
- "depth = (int) 15, "
- "endianness = (int) BYTE_ORDER, "
- "red_mask = 0x7c00, " "green_mask = 0x03e0, " "blue_mask = 0x001f");
- break;
- case VIDEO_PALETTE_RGB565:
- caps = gst_caps_from_string ("video/x-raw-rgb, "
- "bpp = (int) 16, "
- "depth = (int) 16, "
- "endianness = (int) BYTE_ORDER, "
- "red_mask = 0xf800, " "green_mask = 0x07f0, " "blue_mask = 0x001f");
- break;
- case VIDEO_PALETTE_RGB24:
- caps = gst_caps_from_string ("video/x-raw-rgb, "
- "bpp = (int) 24, "
- "depth = (int) 24, "
- "endianness = (int) BIG_ENDIAN, "
- "red_mask = 0xFF0000, "
- "green_mask = 0x00FF00, " "blue_mask = 0x0000FF");
- break;
- case VIDEO_PALETTE_RGB32:
- caps = gst_caps_from_string ("video/x-raw-rgb, "
- "bpp = (int) 32, "
- "depth = (int) 24, "
- "endianness = (int) BIG_ENDIAN, "
- "red_mask = 0xFF000000, "
- "green_mask = 0x00FF0000, " "blue_mask = 0x0000FF00");
- break;
- default:
- g_assert_not_reached ();
- return NULL;
- }
- } else {
- caps = gst_caps_new_simple ("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, fourcc, NULL);
- }
-
- return caps;
-}
-
-static GstCaps *
-gst_v4lsrc_get_any_caps (void)
-{
- gint i;
- GstCaps *caps = gst_caps_new_empty (), *one;
-
- for (i = 0; all_palettes[i] != -1; i++) {
- one = gst_v4lsrc_palette_to_caps (all_palettes[i]);
- gst_caps_append (caps, one);
- }
-
- return caps;
-}
-
-static GstCaps *
-gst_v4lsrc_get_caps (GstBaseSrc * src)
-{
- GstCaps *list;
- GstV4lSrc *v4lsrc = GST_V4LSRC (src);
- struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
- gint width = GST_V4LELEMENT (src)->vcap.minwidth;
- gint height = GST_V4LELEMENT (src)->vcap.minheight;
- gint i;
- gint fps_n, fps_d;
- GList *item;
-
- if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) {
- return gst_v4lsrc_get_any_caps ();
- }
-
- if (!v4lsrc->autoprobe) {
- /* FIXME: query current caps and return those, with _any appended */
- return gst_v4lsrc_get_any_caps ();
- }
-
- if (!v4lsrc->colorspaces) {
- GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes");
- for (i = 0; all_palettes[i] != -1; i++) {
- /* try palette out */
- if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i]))
- continue;
- GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list",
- all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i]));
- v4lsrc->colorspaces = g_list_append (v4lsrc->colorspaces,
- GINT_TO_POINTER (all_palettes[i]));
- }
- GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported",
- g_list_length (v4lsrc->colorspaces));
- if (v4lsrc->autoprobe_fps) {
- GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates");
- v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc);
- }
- }
-
-
- if (!gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)) {
- fps_n = 0;
- fps_d = 1;
- }
-
- list = gst_caps_new_empty ();
- for (item = v4lsrc->colorspaces; item != NULL; item = item->next) {
- GstCaps *one;
-
- one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data));
- if (!one) {
- GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n",
- GPOINTER_TO_INT (item->data));
- continue;
- }
-
- GST_DEBUG_OBJECT (v4lsrc,
- "Device reports w: %d-%d, h: %d-%d, fps: %d/%d for palette %d",
- vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight,
- fps_n, fps_d, GPOINTER_TO_INT (item->data));
-
- if (vcap->minwidth < vcap->maxwidth) {
- gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth,
- vcap->maxwidth, NULL);
- } else {
- gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL);
- }
- if (vcap->minheight < vcap->maxheight) {
- gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight,
- vcap->maxheight, NULL);
- } else {
- gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL);
- }
-
- if (v4lsrc->autoprobe_fps) {
- GstStructure *structure = gst_caps_get_structure (one, 0);
-
- if (v4lsrc->fps_list) {
- gst_structure_set_value (structure, "framerate", v4lsrc->fps_list);
- } else {
- gst_structure_set (structure, "framerate", GST_TYPE_FRACTION,
- fps_n, fps_d, NULL);
- }
- } else {
- gst_caps_set_simple (one, "framerate", GST_TYPE_FRACTION_RANGE,
- 1, 1, 100, 1, NULL);
- }
-
- GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one);
- gst_caps_append (list, one);
- }
-
- return list;
-}
-
-static gboolean
-gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
-{
- GstV4lSrc *v4lsrc;
- guint32 fourcc;
- gint bpp, depth, w, h, palette = -1;
- const GValue *new_fps;
- gint cur_fps_n, cur_fps_d;
- GstStructure *structure;
- struct video_window *vwin;
-
- v4lsrc = GST_V4LSRC (src);
- vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
- /* if we're not open, punt -- we'll get setcaps'd later via negotiate */
- if (!GST_V4L_IS_OPEN (v4lsrc))
- return FALSE;
-
- /* make sure we stop capturing and dealloc buffers */
- if (GST_V4L_IS_ACTIVE (v4lsrc)) {
- if (!gst_v4lsrc_capture_stop (v4lsrc))
- return FALSE;
- if (!gst_v4lsrc_capture_deinit (v4lsrc))
- return FALSE;
- }
-
- /* it's fixed, one struct */
- structure = gst_caps_get_structure (caps, 0);
-
- if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0)
- gst_structure_get_fourcc (structure, "format", &fourcc);
- else
- fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' ');
-
- gst_structure_get_int (structure, "width", &w);
- gst_structure_get_int (structure, "height", &h);
- new_fps = gst_structure_get_value (structure, "framerate");
-
- /* set framerate if it's not already correct */
- if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps_n, &cur_fps_d))
- return FALSE;
-
- if (new_fps) {
- GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h,
- gst_value_get_fraction_numerator (new_fps),
- gst_value_get_fraction_denominator (new_fps));
-
- if (gst_value_get_fraction_numerator (new_fps) != cur_fps_n ||
- gst_value_get_fraction_denominator (new_fps) != cur_fps_d) {
- int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) /
- (gst_value_get_fraction_denominator (new_fps) * 15);
-
- GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index);
- /* set bits 16 to 21 to 0 */
- vwin->flags &= (0x3F00 - 1);
- /* set bits 16 to 21 to the index */
- vwin->flags |= fps_index << 16;
- if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) {
- return FALSE;
- }
- }
- }
-
- switch (fourcc) {
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- palette = VIDEO_PALETTE_YUV420P;
- v4lsrc->buffer_size = ((w + 1) & ~1) * ((h + 1) & ~1) * 1.5;
- break;
- case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
- palette = VIDEO_PALETTE_YUV422;
- v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
- break;
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- palette = VIDEO_PALETTE_UYVY;
- v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
- palette = VIDEO_PALETTE_YUV411P;
- v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
- palette = VIDEO_PALETTE_YUV411;
- v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5;
- break;
- case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
- palette = VIDEO_PALETTE_YUV410P;
- v4lsrc->buffer_size = ((w + 3) & ~3) * ((h + 3) & ~3) * 1.125;
- break;
- case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
- palette = VIDEO_PALETTE_YUV422P;
- v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2;
- break;
- case GST_MAKE_FOURCC ('R', 'G', 'B', ' '):
- gst_structure_get_int (structure, "depth", &depth);
- switch (depth) {
- case 15:
- palette = VIDEO_PALETTE_RGB555;
- v4lsrc->buffer_size = w * h * 2;
- break;
- case 16:
- palette = VIDEO_PALETTE_RGB565;
- v4lsrc->buffer_size = w * h * 2;
- break;
- case 24:
- gst_structure_get_int (structure, "bpp", &bpp);
- switch (bpp) {
- case 24:
- palette = VIDEO_PALETTE_RGB24;
- v4lsrc->buffer_size = w * h * 3;
- break;
- case 32:
- palette = VIDEO_PALETTE_RGB32;
- v4lsrc->buffer_size = w * h * 4;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- if (palette == -1) {
- GST_WARNING_OBJECT (v4lsrc, "palette for fourcc %" GST_FOURCC_FORMAT
- " is -1, refusing link", GST_FOURCC_ARGS (fourcc));
- return FALSE;
- }
-
- GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d",
- w, h, palette);
- /* this only fills in v4lsrc->mmap values */
- if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) {
- GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d",
- w, h, palette);
- return FALSE;
- }
-
- /* first try the negotiated settings using try_capture */
- if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) {
- GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette,
- w, h);
- return FALSE;
- }
-
- if (!gst_v4lsrc_capture_init (v4lsrc))
- return FALSE;
-
- if (!gst_v4lsrc_capture_start (v4lsrc))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query)
-{
- GstV4lSrc *v4lsrc;
- gboolean res = FALSE;
-
- v4lsrc = GST_V4LSRC (bsrc);
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_LATENCY:
- {
- GstClockTime min_latency, max_latency;
- gint fps_n, fps_d;
-
- /* device must be open */
- if (!GST_V4L_IS_OPEN (v4lsrc))
- goto done;
-
- /* we must have a framerate */
- if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)))
- goto done;
-
- /* min latency is the time to capture one frame */
- min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
-
- /* max latency is total duration of the frame buffer */
- max_latency = v4lsrc->mbuf.frames * min_latency;
-
- GST_DEBUG_OBJECT (bsrc,
- "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
- GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
-
- /* we are always live, the min latency is 1 frame and the max latency is
- * the complete buffer of frames. */
- gst_query_set_latency (query, TRUE, min_latency, max_latency);
-
- res = TRUE;
- break;
- }
- default:
- res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
- break;
- }
-done:
- return res;
-}
-
-/* start and stop are not symmetric -- start will open the device, but not start
- capture. it's setcaps that will start capture, which is called via basesrc's
- negotiate method. stop will both stop capture and close the device.
- */
-static gboolean
-gst_v4lsrc_start (GstBaseSrc * src)
-{
- GstV4lSrc *v4lsrc = GST_V4LSRC (src);
-
- if (!GST_BASE_SRC_CLASS (parent_class)->start (src))
- return FALSE;
-
- v4lsrc->offset = 0;
-
- return TRUE;
-}
-
-static gboolean
-gst_v4lsrc_stop (GstBaseSrc * src)
-{
- GstV4lSrc *v4lsrc = GST_V4LSRC (src);
-
- if (GST_V4L_IS_ACTIVE (v4lsrc) && !gst_v4lsrc_capture_stop (v4lsrc))
- return FALSE;
-
- if (GST_V4LELEMENT (v4lsrc)->buffer != NULL) {
- if (!gst_v4lsrc_capture_deinit (v4lsrc))
- return FALSE;
- }
-
- if (!GST_BASE_SRC_CLASS (parent_class)->stop (src))
- return FALSE;
-
- g_list_free (v4lsrc->colorspaces);
- v4lsrc->colorspaces = NULL;
-
- if (v4lsrc->fps_list) {
- g_value_unset (v4lsrc->fps_list);
- g_free (v4lsrc->fps_list);
- v4lsrc->fps_list = NULL;
- }
-
- return TRUE;
-}
-
-static GstFlowReturn
-gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** buf)
-{
- GstV4lSrc *v4lsrc;
- gint num;
-
- v4lsrc = GST_V4LSRC (src);
-
- /* grab a frame from the device */
- if (!gst_v4lsrc_grab_frame (v4lsrc, &num))
- return GST_FLOW_ERROR;
-
- *buf = gst_v4lsrc_buffer_new (v4lsrc, num);
-
- if (v4lsrc->copy_mode) {
- GstBuffer *copy = gst_buffer_copy (*buf);
-
- gst_buffer_unref (*buf);
- *buf = copy;
- }
-
- return GST_FLOW_OK;
-}
--- a/gst_plugins_base/sys/v4l/gstv4lsrc.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/* GStreamer
- *
- * gstv4lsrc.h: BT8x8/V4L video source element
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4LSRC_H__
-#define __GST_V4LSRC_H__
-
-
-#include <gstv4lelement.h>
-
-
-G_BEGIN_DECLS
-
-
-#define GST_TYPE_V4LSRC \
- (gst_v4lsrc_get_type())
-#define GST_V4LSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LSRC,GstV4lSrc))
-#define GST_V4LSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LSRC,GstV4lSrcClass))
-#define GST_IS_V4LSRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LSRC))
-#define GST_IS_V4LSRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LSRC))
-
-
-typedef struct _GstV4lSrc GstV4lSrc;
-typedef struct _GstV4lSrcClass GstV4lSrcClass;
-
-
-enum
-{
- QUEUE_STATE_ERROR = -1,
- QUEUE_STATE_READY_FOR_QUEUE, /* the frame is ready to be queued for capture */
- QUEUE_STATE_QUEUED, /* the frame is queued for capture */
- QUEUE_STATE_SYNCED /* the frame is captured */
-};
-
-
-struct _GstV4lSrc
-{
- GstV4lElement v4lelement;
-
- /* pads */
- GstPad *srcpad;
-
- /* capture/buffer info */
- struct video_mmap mmap;
- struct video_mbuf mbuf;
- guint buffer_size;
- GstClockTime timestamp_sync;
-
- /* num of queued frames and some GThread stuff
- * to wait if there's not enough */
- gint8 *frame_queue_state;
- GMutex *mutex_queue_state;
- GCond *cond_queue_state;
- gint num_queued;
- gint sync_frame, queue_frame;
- gboolean is_capturing;
- GstClockTimeDiff timestamp_offset;
-
- /* True if we want to stop */
- gboolean quit;
-
- gint offset;
-
- /* list of supported colorspaces (as integers) */
- GList *colorspaces;
-
- gboolean autoprobe; /* probe features on startup ? */
- gboolean autoprobe_fps; /* probe fps on startup ? */
- gboolean copy_mode;
-
- GValue *fps_list; /* list of fps probed */
-};
-
-struct _GstV4lSrcClass
-{
- GstV4lElementClass parent_class;
-};
-
-
-GType gst_v4lsrc_get_type (void);
-
-
-G_END_DECLS
-
-
-#endif /* __GST_V4LSRC_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4ltuner.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,328 +0,0 @@
-/* GStreamer
- *
- * gstv4ltuner.c: tuner interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gst/gst.h>
-
-#include "gstv4ltuner.h"
-#include "gstv4lelement.h"
-#include "v4l_calls.h"
-
-static void gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass);
-static void gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel);
-
-static void gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass);
-static void gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm);
-
-static const GList *gst_v4l_tuner_list_channels (GstTuner * tuner);
-static void gst_v4l_tuner_set_channel (GstTuner * tuner,
- GstTunerChannel * channel);
-static GstTunerChannel *gst_v4l_tuner_get_channel (GstTuner * tuner);
-
-static const GList *gst_v4l_tuner_list_norms (GstTuner * tuner);
-static void gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm);
-static GstTunerNorm *gst_v4l_tuner_get_norm (GstTuner * tuner);
-
-static void gst_v4l_tuner_set_frequency (GstTuner * tuner,
- GstTunerChannel * channel, gulong frequency);
-static gulong gst_v4l_tuner_get_frequency (GstTuner * tuner,
- GstTunerChannel * channel);
-static gint gst_v4l_tuner_signal_strength (GstTuner * tuner,
- GstTunerChannel * channel);
-
-static GstTunerNormClass *norm_parent_class = NULL;
-static GstTunerChannelClass *channel_parent_class = NULL;
-
-GType
-gst_v4l_tuner_channel_get_type (void)
-{
- static GType gst_v4l_tuner_channel_type = 0;
-
- if (!gst_v4l_tuner_channel_type) {
- static const GTypeInfo v4l_tuner_channel_info = {
- sizeof (GstV4lTunerChannelClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_v4l_tuner_channel_class_init,
- NULL,
- NULL,
- sizeof (GstV4lTunerChannel),
- 0,
- (GInstanceInitFunc) gst_v4l_tuner_channel_init,
- NULL
- };
-
- gst_v4l_tuner_channel_type =
- g_type_register_static (GST_TYPE_TUNER_CHANNEL,
- "GstV4lTunerChannel", &v4l_tuner_channel_info, 0);
- }
-
- return gst_v4l_tuner_channel_type;
-}
-
-static void
-gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass)
-{
- channel_parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel)
-{
- channel->index = 0;
- channel->audio = 0;
- channel->tuner = 0;
-}
-
-GType
-gst_v4l_tuner_norm_get_type (void)
-{
- static GType gst_v4l_tuner_norm_type = 0;
-
- if (!gst_v4l_tuner_norm_type) {
- static const GTypeInfo v4l_tuner_norm_info = {
- sizeof (GstV4lTunerNormClass),
- NULL,
- NULL,
- (GClassInitFunc) gst_v4l_tuner_norm_class_init,
- NULL,
- NULL,
- sizeof (GstV4lTunerNorm),
- 0,
- (GInstanceInitFunc) gst_v4l_tuner_norm_init,
- NULL
- };
-
- gst_v4l_tuner_norm_type =
- g_type_register_static (GST_TYPE_TUNER_NORM,
- "GstV4lTunerNorm", &v4l_tuner_norm_info, 0);
- }
-
- return gst_v4l_tuner_norm_type;
-}
-
-static void
-gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass)
-{
- norm_parent_class = g_type_class_peek_parent (klass);
-}
-
-static void
-gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm)
-{
- norm->index = 0;
-}
-
-void
-gst_v4l_tuner_interface_init (GstTunerClass * klass)
-{
- /* default virtual functions */
- klass->list_channels = gst_v4l_tuner_list_channels;
- klass->set_channel = gst_v4l_tuner_set_channel;
- klass->get_channel = gst_v4l_tuner_get_channel;
-
- klass->list_norms = gst_v4l_tuner_list_norms;
- klass->set_norm = gst_v4l_tuner_set_norm;
- klass->get_norm = gst_v4l_tuner_get_norm;
-
- klass->set_frequency = gst_v4l_tuner_set_frequency;
- klass->get_frequency = gst_v4l_tuner_get_frequency;
- klass->signal_strength = gst_v4l_tuner_signal_strength;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_tuner_contains_channel (GstV4lElement * v4lelement,
- GstV4lTunerChannel * v4lchannel)
-{
- const GList *item;
-
- for (item = v4lelement->channels; item != NULL; item = item->next)
- if (item->data == v4lchannel)
- return TRUE;
-
- return FALSE;
-}
-
-static const GList *
-gst_v4l_tuner_list_channels (GstTuner * tuner)
-{
- return GST_V4LELEMENT (tuner)->channels;
-}
-
-static void
-gst_v4l_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
- gint norm;
-
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
- g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));
-
- gst_v4l_get_chan_norm (v4lelement, NULL, &norm);
- gst_v4l_set_chan_norm (v4lelement, v4lchannel->index, norm);
-}
-
-static GstTunerChannel *
-gst_v4l_tuner_get_channel (GstTuner * tuner)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GList *item;
- gint channel;
-
- /* assert that we're opened */
- g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);
-
- gst_v4l_get_chan_norm (v4lelement, &channel, NULL);
-
- for (item = v4lelement->channels; item != NULL; item = item->next) {
- if (channel == GST_V4L_TUNER_CHANNEL (item->data)->index)
- return GST_TUNER_CHANNEL (item->data);
- }
-
- return NULL;
-}
-
-static G_GNUC_UNUSED gboolean
-gst_v4l_tuner_contains_norm (GstV4lElement * v4lelement,
- GstV4lTunerNorm * v4lnorm)
-{
- const GList *item;
-
- for (item = v4lelement->norms; item != NULL; item = item->next)
- if (item->data == v4lnorm)
- return TRUE;
-
- return FALSE;
-}
-
-static const GList *
-gst_v4l_tuner_list_norms (GstTuner * tuner)
-{
- return GST_V4LELEMENT (tuner)->norms;
-}
-
-static void
-gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GstV4lTunerNorm *v4lnorm = GST_V4L_TUNER_NORM (norm);
- gint channel;
-
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
- g_return_if_fail (gst_v4l_tuner_contains_norm (v4lelement, v4lnorm));
-
- gst_v4l_get_chan_norm (v4lelement, &channel, NULL);
- gst_v4l_set_chan_norm (v4lelement, channel, v4lnorm->index);
-}
-
-static GstTunerNorm *
-gst_v4l_tuner_get_norm (GstTuner * tuner)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GList *item;
- gint norm;
-
- /* assert that we're opened */
- g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL);
-
- gst_v4l_get_chan_norm (v4lelement, NULL, &norm);
-
- for (item = v4lelement->norms; item != NULL; item = item->next) {
- if (norm == GST_V4L_TUNER_NORM (item->data)->index)
- return GST_TUNER_NORM (item->data);
- }
-
- return NULL;
-}
-
-static void
-gst_v4l_tuner_set_frequency (GstTuner * tuner,
- GstTunerChannel * channel, gulong frequency)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
- gint chan;
-
- /* assert that we're opened and that we're using a known item */
- g_return_if_fail (GST_V4L_IS_OPEN (v4lelement));
- g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
- GST_TUNER_CHANNEL_FREQUENCY));
- g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel));
-
- gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
- if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) {
- gst_v4l_set_frequency (v4lelement, v4lchannel->tuner, frequency);
- }
-}
-
-static gulong
-gst_v4l_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
- gint chan;
- gulong frequency = 0;
-
- /* assert that we're opened and that we're using a known item */
- g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
- g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
- GST_TUNER_CHANNEL_FREQUENCY), 0);
- g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement,
- v4lchannel), 0);
-
- gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
- if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) {
- gst_v4l_get_frequency (v4lelement, v4lchannel->tuner, &frequency);
- }
-
- return frequency;
-}
-
-static gint
-gst_v4l_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (tuner);
- GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel);
- gint chan;
- guint signal = 0;
-
- /* assert that we're opened and that we're using a known item */
- g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0);
- g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
- GST_TUNER_CHANNEL_FREQUENCY), 0);
- g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement,
- v4lchannel), 0);
-
- gst_v4l_get_chan_norm (v4lelement, &chan, NULL);
- if (chan == GST_V4L_TUNER_CHANNEL (channel)->index &&
- GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
- gst_v4l_get_signal (v4lelement, v4lchannel->tuner, &signal);
- }
-
- return (gint) signal;
-}
--- a/gst_plugins_base/sys/v4l/gstv4ltuner.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/* GStreamer
- *
- * gstv4ltuner.h: tuner interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4L_TUNER_H__
-#define __GST_V4L_TUNER_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/tuner.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_V4L_TUNER_CHANNEL \
- (gst_v4l_tuner_channel_get_type ())
-#define GST_V4L_TUNER_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_CHANNEL, \
- GstV4lTunerChannel))
-#define GST_V4L_TUNER_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_CHANNEL, \
- GstV4lTunerChannelClass))
-#define GST_IS_V4L_TUNER_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_CHANNEL))
-#define GST_IS_V4L_TUNER_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_CHANNEL))
-
-typedef struct _GstV4lTunerChannel {
- GstTunerChannel parent;
-
- gint index;
- gint tuner;
- gint audio;
-} GstV4lTunerChannel;
-
-typedef struct _GstV4lTunerChannelClass {
- GstTunerChannelClass parent;
-} GstV4lTunerChannelClass;
-
-#define GST_TYPE_V4L_TUNER_NORM \
- (gst_v4l_tuner_norm_get_type ())
-#define GST_V4L_TUNER_NORM(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_NORM, \
- GstV4lTunerNorm))
-#define GST_V4L_TUNER_NORM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_NORM, \
- GstV4lTunerNormClass))
-#define GST_IS_V4L_TUNER_NORM(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_NORM))
-#define GST_IS_V4L_TUNER_NORM_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_NORM))
-
-typedef struct _GstV4lTunerNorm {
- GstTunerNorm parent;
-
- gint index;
-} GstV4lTunerNorm;
-
-typedef struct _GstV4lTunerNormClass {
- GstTunerNormClass parent;
-} GstV4lTunerNormClass;
-
-GType gst_v4l_tuner_channel_get_type (void);
-GType gst_v4l_tuner_norm_get_type (void);
-
-void gst_v4l_tuner_interface_init (GstTunerClass *klass);
-
-#endif /* __GST_V4L_TUNER_H__ */
--- a/gst_plugins_base/sys/v4l/gstv4lxoverlay.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/* GStreamer
- *
- * gstv4lxoverlay.c: X-based overlay interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <sys/stat.h>
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include "gstv4lxoverlay.h"
-#include "gstv4lelement.h"
-#include "v4l_calls.h"
-
-GST_DEBUG_CATEGORY_STATIC (v4lxv_debug);
-#define GST_CAT_DEFAULT v4lxv_debug
-
-struct _GstV4lXv
-{
- Display *dpy;
- gint port, idle_id;
- GMutex *mutex;
-};
-
-static void gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay,
- XID xwindow_id);
-
-void
-gst_v4l_xoverlay_interface_init (GstXOverlayClass * klass)
-{
- /* default virtual functions */
- klass->set_xwindow_id = gst_v4l_xoverlay_set_xwindow_id;
-
- GST_DEBUG_CATEGORY_INIT (v4lxv_debug, "v4lxv", 0,
- "V4L XOverlay interface debugging");
-}
-
-static void
-gst_v4l_xoverlay_open (GstV4lElement * v4lelement)
-{
- struct stat s;
- GstV4lXv *v4lxv;
- const gchar *name = g_getenv ("DISPLAY");
- unsigned int ver, rel, req, ev, err, anum;
- int i, id = 0, first_id = 0, min;
- XvAdaptorInfo *ai;
- Display *dpy;
-
- /* we need a display, obviously */
- if (!name || !(dpy = XOpenDisplay (name))) {
- GST_WARNING ("No $DISPLAY set or failed to open - no overlay");
- return;
- }
-
- /* First let's check that XVideo extension is available */
- if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) {
- GST_WARNING ("Xv extension not available - no overlay");
- XCloseDisplay (dpy);
- return;
- }
-
- /* find port that belongs to this device */
- if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) {
- GST_WARNING ("Xv extension not supported - no overlay");
- XCloseDisplay (dpy);
- return;
- }
- if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) {
- GST_WARNING ("Failed to query Xv adaptors");
- XCloseDisplay (dpy);
- return;
- }
- if (fstat (v4lelement->video_fd, &s) < 0) {
- GST_ERROR ("Failed to stat() file descriptor: %s", g_strerror (errno));
- XCloseDisplay (dpy);
- return;
- }
- min = s.st_rdev & 0xff;
- for (i = 0; i < anum; i++) {
- if (!strcmp (ai[i].name, "video4linux")) {
- if (first_id == 0)
- first_id = ai[i].base_id;
-
- /* hmm... */
- if (first_id != 0 && ai[i].base_id == first_id + min)
- id = ai[i].base_id;
- }
- }
- XvFreeAdaptorInfo (ai);
-
- if (id == 0) {
- GST_WARNING ("Did not find XvPortID for device - no overlay");
- XCloseDisplay (dpy);
- return;
- }
-
- v4lxv = g_new0 (GstV4lXv, 1);
- v4lxv->dpy = dpy;
- v4lxv->port = id;
- v4lxv->mutex = g_mutex_new ();
- v4lxv->idle_id = 0;
- v4lelement->xv = v4lxv;
-
- if (v4lelement->xwindow_id) {
- gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement),
- v4lelement->xwindow_id);
- }
-}
-
-static void
-gst_v4l_xoverlay_close (GstV4lElement * v4lelement)
-{
- GstV4lXv *v4lxv = v4lelement->xv;
-
- if (!v4lelement->xv)
- return;
-
- if (v4lelement->xwindow_id) {
- gst_v4l_xoverlay_set_xwindow_id (GST_X_OVERLAY (v4lelement), 0);
- }
-
- XCloseDisplay (v4lxv->dpy);
- g_mutex_free (v4lxv->mutex);
- if (v4lxv->idle_id)
- g_source_remove (v4lxv->idle_id);
- g_free (v4lxv);
- v4lelement->xv = NULL;
-}
-
-void
-gst_v4l_xoverlay_start (GstV4lElement * v4lelement)
-{
- if (v4lelement->xwindow_id) {
- gst_v4l_xoverlay_open (v4lelement);
- }
-}
-
-void
-gst_v4l_xoverlay_stop (GstV4lElement * v4lelement)
-{
- gst_v4l_xoverlay_close (v4lelement);
-}
-
-static gboolean
-idle_refresh (gpointer data)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (data);
- GstV4lXv *v4lxv = v4lelement->xv;
- XWindowAttributes attr;
-
- if (v4lxv) {
- g_mutex_lock (v4lxv->mutex);
-
- XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
- XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
- DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
- 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
-
- v4lxv->idle_id = 0;
- g_mutex_unlock (v4lxv->mutex);
- }
-
- /* once */
- return FALSE;
-}
-
-static void
-gst_v4l_xoverlay_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
- GstV4lElement *v4lelement = GST_V4LELEMENT (overlay);
- GstV4lXv *v4lxv;
- XWindowAttributes attr;
- gboolean change = (v4lelement->xwindow_id != xwindow_id);
-
- GST_LOG_OBJECT (v4lelement, "Changing port to %lx", xwindow_id);
-
- if (!v4lelement->xv && GST_V4L_IS_OPEN (v4lelement))
- gst_v4l_xoverlay_open (v4lelement);
-
- v4lxv = v4lelement->xv;
-
- if (v4lxv)
- g_mutex_lock (v4lxv->mutex);
-
- if (change) {
- if (v4lelement->xwindow_id && v4lxv) {
- GST_DEBUG_OBJECT (v4lelement,
- "Disabling port %lx", v4lelement->xwindow_id);
-
- XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 0);
- XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 0);
- XvStopVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id);
- }
-
- v4lelement->xwindow_id = xwindow_id;
- }
-
- if (!v4lxv || xwindow_id == 0) {
- if (v4lxv)
- g_mutex_unlock (v4lxv->mutex);
- return;
- }
-
- if (change) {
- GST_DEBUG_OBJECT (v4lelement, "Enabling port %lx", xwindow_id);
-
- /* draw */
- XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 1);
- XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 1);
- }
-
- XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr);
- XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id,
- DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)),
- 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height);
-
- if (v4lxv->idle_id)
- g_source_remove (v4lxv->idle_id);
- v4lxv->idle_id = g_idle_add (idle_refresh, v4lelement);
- g_mutex_unlock (v4lxv->mutex);
-}
--- a/gst_plugins_base/sys/v4l/gstv4lxoverlay.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/* GStreamer
- *
- * gstv4lxoverlay.h: tv mixer interface implementation for V4L
- *
- * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_V4L_X_OVERLAY_H__
-#define __GST_V4L_X_OVERLAY_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/xoverlay.h>
-
-#include "gstv4lelement.h"
-
-G_BEGIN_DECLS
-
-void gst_v4l_xoverlay_interface_init (GstXOverlayClass *klass);
-
-void gst_v4l_xoverlay_start (GstV4lElement * v4lelement);
-void gst_v4l_xoverlay_stop (GstV4lElement * v4lelement);
-
-G_END_DECLS
-
-#endif /* __GST_V4L_X_OVERLAY_H__ */
--- a/gst_plugins_base/sys/v4l/v4l_calls.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,723 +0,0 @@
-/* GStreamer
- *
- * v4l_calls.c: generic V4L calls
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <gst/gst.h>
-#include <gst/interfaces/tuner.h>
-#include <gst/interfaces/colorbalance.h>
-
-#include "v4l_calls.h"
-#include "gstv4ltuner.h"
-#include "gstv4lcolorbalance.h"
-
-#include "gstv4lsrc.h"
-/* #include "gstv4lmjpegsrc.h" */
-/* #include "gstv4lmjpegsink.h" */
-
-GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
-#define GST_CAT_DEFAULT v4l_debug
-
-static const char *picture_name[] = {
- "Hue",
- "Brightness",
- "Contrast",
- "Saturation",
- NULL
-};
-
-G_GNUC_UNUSED static const char *audio_name[] = {
- "Volume",
- "Mute",
- "Mode",
- NULL
-};
-
-static const char *norm_name[] = {
- "PAL",
- "NTSC",
- "SECAM",
- NULL
-};
-
-/******************************************************
- * gst_v4l_get_capabilities():
- * get the device's capturing capabilities
- * sets v4lelement->vcap and v4lelement->vwin
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_capabilities (GstV4lElement * v4lelement)
-{
- GST_DEBUG_OBJECT (v4lelement, "getting capabilities");
- GST_V4L_CHECK_OPEN (v4lelement);
-
- if (ioctl (v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("error getting capabilities %s of from device %s",
- g_strerror (errno), v4lelement->videodev));
- return FALSE;
- }
-
- if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("error getting window properties %s of from device %s",
- g_strerror (errno), v4lelement->videodev));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/******************************************************
- * gst_v4l_set_window_properties():
- * set the device's capturing parameters (vwin)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_window_properties (GstV4lElement * v4lelement)
-{
- struct video_window vwin;
-
- GST_DEBUG_OBJECT (v4lelement, "setting window flags 0x%x to device %s",
- v4lelement->vwin.flags, v4lelement->videodev);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &(v4lelement->vwin)) < 0) {
- GST_DEBUG_OBJECT (v4lelement,
- "could not ioctl window properties 0x%x to device %s",
- v4lelement->vwin.flags, v4lelement->videodev);
- return FALSE;
- }
-
- /* get it again to make sure we have it correctly */
- if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(vwin)) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("error getting window properties %s of from device %s",
- g_strerror (errno), v4lelement->videodev));
- return FALSE;
- }
- if (vwin.flags != v4lelement->vwin.flags) {
- GST_DEBUG_OBJECT (v4lelement, "set 0x%x but got 0x%x back",
- v4lelement->vwin.flags, vwin.flags);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/******************************************************
- * gst_v4l_open():
- * open the video device (v4lelement->videodev)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_open (GstV4lElement * v4lelement)
-{
- int num;
-
- GST_DEBUG_OBJECT (v4lelement, "opening device %s", v4lelement->videodev);
- GST_V4L_CHECK_NOT_OPEN (v4lelement);
- GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
- /* be sure we have a device */
- if (!v4lelement->videodev) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
- (_("No device specified.")), (NULL));
- return FALSE;
- }
-
- /* open the device */
- v4lelement->video_fd = open (v4lelement->videodev, O_RDWR);
- if (!GST_V4L_IS_OPEN (v4lelement)) {
- if (errno == ENODEV || errno == ENOENT) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
- (_("Device \"%s\" does not exist."), v4lelement->videodev), (NULL));
- return FALSE;
- }
- if (errno == EBUSY) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, BUSY,
- (_("Device \"%s\" is already being used."), v4lelement->videodev),
- (NULL));
- return FALSE;
- }
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, OPEN_READ_WRITE,
- (_("Could not open device \"%s\" for reading and writing."),
- v4lelement->videodev), GST_ERROR_SYSTEM);
- return FALSE;
- }
-
- /* get capabilities */
- if (!gst_v4l_get_capabilities (v4lelement)) {
- close (v4lelement->video_fd);
- v4lelement->video_fd = -1;
- return FALSE;
- }
-
- /* device type check */
- if ((GST_IS_V4LSRC (v4lelement) &&
- !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) {
-/* (GST_IS_V4LMJPEGSRC (v4lelement) && */
-/* !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */
-/* (GST_IS_V4LMJPEGSINK (v4lelement) && */
-/* !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type));
- close (v4lelement->video_fd);
- v4lelement->video_fd = -1;
- return FALSE;
- }
-
- GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully",
- v4lelement->vcap.name, v4lelement->videodev);
-
- /* norms + inputs, for the tuner interface */
- for (num = 0; norm_name[num] != NULL; num++) {
- GstV4lTunerNorm *v4lnorm = g_object_new (GST_TYPE_V4L_TUNER_NORM,
- NULL);
- GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm);
-
- norm->label = g_strdup (norm_name[num]);
- if (num == 1)
- gst_value_set_fraction (&norm->framerate, 30000, 1001);
- else
- gst_value_set_fraction (&norm->framerate, 25, 1);
-
- v4lnorm->index = num;
- v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm);
- }
- v4lelement->channels = gst_v4l_get_chan_names (v4lelement);
-
- for (num = 0; picture_name[num] != NULL; num++) {
- GstV4lColorBalanceChannel *v4lchannel =
- g_object_new (GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, NULL);
- GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (v4lchannel);
-
- channel->label = g_strdup (picture_name[num]);
- channel->min_value = 0;
- channel->max_value = 65535;
- v4lchannel->index = num;
- v4lelement->colors = g_list_append (v4lelement->colors, channel);
- }
-
- GST_DEBUG_OBJECT (v4lelement, "Setting default norm/input");
- gst_v4l_set_chan_norm (v4lelement, 0, 0);
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_close():
- * close the video device (v4lelement->video_fd)
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_close (GstV4lElement * v4lelement)
-{
- GST_DEBUG_OBJECT (v4lelement, "closing device");
- GST_V4L_CHECK_OPEN (v4lelement);
- GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
- close (v4lelement->video_fd);
- v4lelement->video_fd = -1;
-
- g_list_foreach (v4lelement->channels, (GFunc) g_object_unref, NULL);
- g_list_free (v4lelement->channels);
- v4lelement->channels = NULL;
-
- g_list_foreach (v4lelement->norms, (GFunc) g_object_unref, NULL);
- g_list_free (v4lelement->norms);
- v4lelement->norms = NULL;
-
- g_list_foreach (v4lelement->colors, (GFunc) g_object_unref, NULL);
- g_list_free (v4lelement->colors);
- v4lelement->colors = NULL;
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_num_chans()
- * return value: the number of video input channels
- ******************************************************/
-
-static gint
-gst_v4l_get_num_chans (GstV4lElement * v4lelement)
-{
- GST_DEBUG_OBJECT (v4lelement, "getting number of channels");
- GST_V4L_CHECK_OPEN (v4lelement);
-
- return v4lelement->vcap.channels;
-}
-
-
-/******************************************************
- * gst_v4l_get_chan_names()
- * return value: a GList containing the channel names
- ******************************************************/
-
-GList *
-gst_v4l_get_chan_names (GstV4lElement * v4lelement)
-{
- struct video_channel vchan;
- GList *list = NULL;
- gint i;
-
- GST_DEBUG_OBJECT (v4lelement, "getting channel names");
-
- if (!GST_V4L_IS_OPEN (v4lelement))
- return NULL;
-
- for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) {
- GstV4lTunerChannel *v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL,
- NULL);
- GstTunerChannel *channel = GST_TUNER_CHANNEL (v4lchannel);
-
- vchan.channel = i;
- if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
- return NULL; /* memleak... */
- channel->label = g_strdup (vchan.name);
- channel->flags = GST_TUNER_CHANNEL_INPUT;
- v4lchannel->index = i;
- if (vchan.flags & VIDEO_VC_TUNER) {
- struct video_tuner vtun;
- gint n;
-
- for (n = 0;; n++) {
- if (n >= vchan.tuners) {
- vtun.tuner = 0; /* default */
- } else {
- vtun.tuner = n;
- if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
- continue; /* no more tuners */
- if (strcmp (vtun.name, vchan.name) != 0) {
- continue; /* not this one */
- }
- }
- v4lchannel->tuner = n;
- channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
- channel->freq_multiplicator =
- 62.5 * ((vtun.flags & VIDEO_TUNER_LOW) ? 1 : 1000);
- channel->min_frequency = vtun.rangelow;
- channel->max_frequency = vtun.rangehigh;
- channel->min_signal = 0;
- channel->max_signal = 0xffff;
- break;
- }
-
- }
- if (vchan.flags & VIDEO_VC_AUDIO) {
- struct video_audio vaud;
- gint n;
-
- for (n = 0; n < v4lelement->vcap.audios; n++) {
- vaud.audio = n;
- if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vaud) < 0)
- continue;
- if (!strcmp (vaud.name, vchan.name)) {
- v4lchannel->audio = n;
- channel->flags |= GST_TUNER_CHANNEL_AUDIO;
- break;
- }
- }
- }
- list = g_list_append (list, (gpointer) channel);
- }
-
- return list;
-}
-
-
-/******************************************************
- * gst_v4l_get_chan_norm():
- * get the currently active video-channel and it's
- * norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_chan_norm (GstV4lElement * v4lelement, gint * channel, gint * norm)
-{
- GST_DEBUG_OBJECT (v4lelement, "getting current channel and norm");
- GST_V4L_CHECK_OPEN (v4lelement);
-
- if (channel)
- *channel = v4lelement->vchan.channel;
- if (norm)
- *norm = v4lelement->vchan.norm;
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_chan_norm():
- * set a new active channel and it's norm
- * (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_chan_norm (GstV4lElement * v4lelement, gint channel, gint norm)
-{
- GST_DEBUG_OBJECT (v4lelement, "setting channel = %d, norm = %d (%s)",
- channel, norm, norm_name[norm]);
- GST_V4L_CHECK_OPEN (v4lelement);
- //GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
-
- v4lelement->vchan.channel = channel;
- v4lelement->vchan.norm = norm;
-
- if (ioctl (v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting the channel/norm settings: %s", g_strerror (errno)));
- return FALSE;
- }
-
- if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting the channel/norm settings: %s", g_strerror (errno)));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_signal():
- * get the current signal
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_signal (GstV4lElement * v4lelement, gint tunernum, guint * signal)
-{
- struct video_tuner tuner;
-
- GST_DEBUG_OBJECT (v4lelement, "getting tuner signal");
- GST_V4L_CHECK_OPEN (v4lelement);
-
- tuner.tuner = tunernum;
- if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &tuner) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting tuner signal: %s", g_strerror (errno)));
- return FALSE;
- }
-
- *signal = tuner.signal;
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_frequency():
- * get the current frequency
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_frequency (GstV4lElement * v4lelement,
- gint tunernum, gulong * frequency)
-{
- struct video_tuner vtun;
- GstTunerChannel *channel;
-
- GST_DEBUG_OBJECT (v4lelement, "getting tuner frequency");
- GST_V4L_CHECK_OPEN (v4lelement);
-
- channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
-
- /* check that this is the current input */
- vtun.tuner = tunernum;
- if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
- return FALSE;
- if (strcmp (vtun.name, v4lelement->vchan.name))
- return FALSE;
-
- if (ioctl (v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting tuner frequency: %s", g_strerror (errno)));
- return FALSE;
- }
-
- *frequency = *frequency * channel->freq_multiplicator;
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_frequency():
- * set frequency
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_frequency (GstV4lElement * v4lelement,
- gint tunernum, gulong frequency)
-{
- struct video_tuner vtun;
- GstTunerChannel *channel;
-
- GST_DEBUG_OBJECT (v4lelement, "setting tuner frequency to %lu", frequency);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
-
- /* check that this is the current input */
- vtun.tuner = tunernum;
- if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
- return FALSE;
- if (strcmp (vtun.name, v4lelement->vchan.name))
- return FALSE;
-
- frequency = frequency / channel->freq_multiplicator;
-
- if (ioctl (v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting tuner frequency: %s", g_strerror (errno)));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_picture():
- * get a picture value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_picture (GstV4lElement * v4lelement,
- GstV4lPictureType type, gint * value)
-{
- struct video_picture vpic;
-
- GST_DEBUG_OBJECT (v4lelement, "getting picture property type %d (%s)", type,
- picture_name[type]);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting picture parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- switch (type) {
- case V4L_PICTURE_HUE:
- *value = vpic.hue;
- break;
- case V4L_PICTURE_BRIGHTNESS:
- *value = vpic.brightness;
- break;
- case V4L_PICTURE_CONTRAST:
- *value = vpic.contrast;
- break;
- case V4L_PICTURE_SATURATION:
- *value = vpic.colour;
- break;
- default:
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting picture parameters: unknown type %d", type));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_picture():
- * set a picture value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_picture (GstV4lElement * v4lelement,
- GstV4lPictureType type, gint value)
-{
- struct video_picture vpic;
-
- GST_DEBUG_OBJECT (v4lelement, "setting picture type %d (%s) to value %d",
- type, picture_name[type], value);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting picture parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- switch (type) {
- case V4L_PICTURE_HUE:
- vpic.hue = value;
- break;
- case V4L_PICTURE_BRIGHTNESS:
- vpic.brightness = value;
- break;
- case V4L_PICTURE_CONTRAST:
- vpic.contrast = value;
- break;
- case V4L_PICTURE_SATURATION:
- vpic.colour = value;
- break;
- default:
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting picture parameters: unknown type %d", type));
- return FALSE;
- }
-
- if (ioctl (v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting picture parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_get_audio():
- * get some audio value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_get_audio (GstV4lElement * v4lelement,
- gint audionum, GstV4lAudioType type, gint * value)
-{
- struct video_audio vau;
-
- GST_DEBUG_OBJECT (v4lelement, "getting audio parameter type %d (%s)", type,
- audio_name[type]);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- vau.audio = audionum;
- if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting audio parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- switch (type) {
- case V4L_AUDIO_MUTE:
- *value = (vau.flags & VIDEO_AUDIO_MUTE);
- break;
- case V4L_AUDIO_VOLUME:
- *value = vau.volume;
- break;
- case V4L_AUDIO_MODE:
- *value = vau.mode;
- break;
- default:
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting audio parameters: unknown type %d", type));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4l_set_audio():
- * set some audio value
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4l_set_audio (GstV4lElement * v4lelement,
- gint audionum, GstV4lAudioType type, gint value)
-{
- struct video_audio vau;
-
- GST_DEBUG_OBJECT (v4lelement,
- "setting audio parameter type %d (%s) to value %d", type,
- audio_name[type], value);
- GST_V4L_CHECK_OPEN (v4lelement);
-
- vau.audio = audionum;
- if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error getting audio parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- switch (type) {
- case V4L_AUDIO_MUTE:
- if (!(vau.flags & VIDEO_AUDIO_MUTABLE)) {
- GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
- ("Error setting audio mute: (un)setting mute is not supported"));
- return FALSE;
- }
- if (value)
- vau.flags |= VIDEO_AUDIO_MUTE;
- else
- vau.flags &= ~VIDEO_AUDIO_MUTE;
- break;
- case V4L_AUDIO_VOLUME:
- if (!(vau.flags & VIDEO_AUDIO_VOLUME)) {
- GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
- ("Error setting audio volume: setting volume is not supported"));
- return FALSE;
- }
- vau.volume = value;
- break;
- case V4L_AUDIO_MODE:
- vau.mode = value;
- break;
- default:
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting audio parameters: unknown type %d", type));
- return FALSE;
- }
-
- if (ioctl (v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0) {
- GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
- ("Error setting audio parameters: %s", g_strerror (errno)));
- return FALSE;
- }
-
- return TRUE;
-}
--- a/gst_plugins_base/sys/v4l/v4l_calls.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/* GStreamer
- *
- * v4l_calls.h: header for generic V4L calls
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __V4L_CALLS_H__
-#define __V4L_CALLS_H__
-
-#include "gstv4lelement.h"
-#include "gst/gst-i18n-plugin.h"
-
-
-G_BEGIN_DECLS
-
-
-/* simple check whether the device is open */
-#define GST_V4L_IS_OPEN(element) \
- (GST_V4LELEMENT (element)->video_fd > 0)
-
-/* check whether the device is 'active' */
-#define GST_V4L_IS_ACTIVE(element) \
- (GST_V4LELEMENT (element)->buffer != NULL)
-
-#define GST_V4L_IS_OVERLAY(element) \
- (GST_V4LELEMENT (element)->vcap.type & VID_TYPE_OVERLAY)
-
-/* checks whether the current v4lelement has already been open()'ed or not */
-#define GST_V4L_CHECK_OPEN(element) \
- if (!GST_V4L_IS_OPEN (element)) \
- { \
- GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
- (_("Device is not open.")), (NULL)); \
- return FALSE; \
- }
-
-/* checks whether the current v4lelement is close()'ed or whether it is still open */
-#define GST_V4L_CHECK_NOT_OPEN(element) \
- if (GST_V4L_IS_OPEN (element)) \
- { \
- GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
- (_("Device is open.")), (NULL)); \
- return FALSE; \
- }
-
-/* checks whether the current v4lelement does video overlay */
-#define GST_V4L_CHECK_OVERLAY(element) \
- if (!(element->vcap.type & VID_TYPE_OVERLAY)) \
- { \
- GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \
- (NULL), ("Device cannot handle overlay")); \
- return FALSE; \
- }
-
-/* checks whether we're in capture mode or not */
-#define GST_V4L_CHECK_ACTIVE(element) \
- if (!GST_V4L_IS_ACTIVE (element)) \
- { \
- GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
- (NULL), ("Device is not in streaming mode")); \
- return FALSE; \
- }
-
-/* checks whether we're out of capture mode or not */
-#define GST_V4L_CHECK_NOT_ACTIVE(element) \
- if (GST_V4L_IS_ACTIVE (element)) \
- { \
- GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \
- (NULL), ("Device is in streaming mode")); \
- return FALSE; \
- }
-
-
-typedef enum {
- V4L_PICTURE_HUE = 0,
- V4L_PICTURE_BRIGHTNESS,
- V4L_PICTURE_CONTRAST,
- V4L_PICTURE_SATURATION,
-} GstV4lPictureType;
-
-typedef enum {
- V4L_AUDIO_VOLUME = 0,
- V4L_AUDIO_MUTE,
- V4L_AUDIO_MODE, /* stereo, mono, ... (see videodev.h) */
-} GstV4lAudioType;
-
-
-/* open/close the device */
-gboolean gst_v4l_open (GstV4lElement *v4lelement);
-gboolean gst_v4l_close (GstV4lElement *v4lelement);
-
-/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */
-gboolean gst_v4l_get_chan_norm (GstV4lElement *v4lelement,
- gint *channel,
- gint *norm);
-gboolean gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
- gint channel,
- gint norm);
-GList *gst_v4l_get_chan_names (GstV4lElement *v4lelement);
-
-/* frequency control */
-gboolean gst_v4l_get_signal (GstV4lElement *v4lelement,
- gint tunernum,
- guint *signal);
-gboolean gst_v4l_get_frequency (GstV4lElement *v4lelement,
- gint tunernum,
- gulong *frequency);
-gboolean gst_v4l_set_frequency (GstV4lElement *v4lelement,
- gint tunernum,
- gulong frequency);
-
-/* picture control */
-gboolean gst_v4l_get_picture (GstV4lElement *v4lelement,
- GstV4lPictureType type,
- gint *value);
-gboolean gst_v4l_set_picture (GstV4lElement *v4lelement,
- GstV4lPictureType type,
- gint value);
-
-/* audio control */
-gboolean gst_v4l_get_audio (GstV4lElement *v4lelement,
- gint audionum,
- GstV4lAudioType type,
- gint *value);
-gboolean gst_v4l_set_audio (GstV4lElement *v4lelement,
- gint audionum,
- GstV4lAudioType type,
- gint value);
-
-/* functions that v4lsrc needs */
-gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement);
-gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement);
-
-
-G_END_DECLS
-
-
-#endif /* __V4L_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lmjpegsink_calls.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* GStreamer
- *
- * v4lmjpegsink_calls.c: functions for hardware MJPEG video sink
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __V4L_MJPEG_SINK_CALLS_H__
-#define __V4L_MJPEG_SINK_CALLS_H__
-
-#include "gstv4lmjpegsink.h"
-#include "v4l_calls.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/* frame playback on device */
-gboolean gst_v4lmjpegsink_set_buffer (GstV4lMjpegSink *v4lmjpegsink,
- gint numbufs,
- gint bufsize);
-gboolean gst_v4lmjpegsink_set_playback (GstV4lMjpegSink *v4lmjpegsink,
- gint width,
- gint height,
- gint x_offset,
- gint y_offset,
- gint norm,
- gint interlacing);
-gboolean gst_v4lmjpegsink_playback_init (GstV4lMjpegSink *v4lmjpegsink);
-gboolean gst_v4lmjpegsink_playback_start (GstV4lMjpegSink *v4lmjpegsink);
-guint8 * gst_v4lmjpegsink_get_buffer (GstV4lMjpegSink *v4lmjpegsink,
- gint num);
-gboolean gst_v4lmjpegsink_play_frame (GstV4lMjpegSink *v4lmjpegsink,
- gint num);
-gboolean gst_v4lmjpegsink_wait_frame (GstV4lMjpegSink *v4lmjpegsink,
- gint *num);
-gboolean gst_v4lmjpegsink_playback_stop (GstV4lMjpegSink *v4lmjpegsink);
-gboolean gst_v4lmjpegsink_playback_deinit (GstV4lMjpegSink *v4lmjpegsink);
-
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __V4L_MJPEG_SINK_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lmjpegsrc_calls.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* GStreamer
- *
- * v4lmjpegsrc_calls.h: functions for hardware MJPEG video source
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __V4L_MJPEG_SRC_CALLS_H__
-#define __V4L_MJPEG_SRC_CALLS_H__
-
-#include "gstv4lmjpegsrc.h"
-#include "v4l_calls.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/* frame grabbing/capture */
-gboolean gst_v4lmjpegsrc_set_buffer (GstV4lMjpegSrc *v4lmjpegsrc,
- gint numbufs,
- gint bufsize);
-gboolean gst_v4lmjpegsrc_set_capture (GstV4lMjpegSrc *v4lmjpegsrc,
- gint decimation,
- gint quality);
-gboolean gst_v4lmjpegsrc_set_capture_m (GstV4lMjpegSrc *v4lmjpegsrc,
- gint x_offset,
- gint y_offset,
- gint width,
- gint height,
- gint h_decimation,
- gint v_decimation,
- gint quality);
-gboolean gst_v4lmjpegsrc_capture_init (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_capture_start (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_grab_frame (GstV4lMjpegSrc *v4lmjpegsrc,
- gint *num,
- gint *size);
-guint8 * gst_v4lmjpegsrc_get_buffer (GstV4lMjpegSrc *v4lmjpegsrc,
- gint num);
-gboolean gst_v4lmjpegsrc_requeue_frame (GstV4lMjpegSrc *v4lmjpegsrc,
- gint num);
-gboolean gst_v4lmjpegsrc_capture_stop (GstV4lMjpegSrc *v4lmjpegsrc);
-gboolean gst_v4lmjpegsrc_capture_deinit (GstV4lMjpegSrc *v4lmjpegsrc);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __V4L_MJPEG_SRC_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/v4lsrc_calls.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,740 +0,0 @@
-/* GStreamer
- *
- * v4lsrc_calls.c: generic V4L source functions
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <errno.h>
-#include "v4lsrc_calls.h"
-#include <sys/time.h>
-
-/* number of buffers to be queued *at least* before syncing */
-#define MIN_BUFFERS_QUEUED 2
-
-/* On some systems MAP_FAILED seems to be missing */
-#ifndef MAP_FAILED
-#define MAP_FAILED ( (caddr_t) -1 )
-#endif
-
-GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
-
-#define GST_CAT_DEFAULT v4l_debug
-
-#ifndef GST_DISABLE_GST_DEBUG
-/* palette names */
-static const char *v4l_palette_name[] = {
- "", /* 0 */
- "grayscale", /* VIDEO_PALETTE_GREY */
- "Hi-420", /* VIDEO_PALETTE_HI420 */
- "16-bit RGB (RGB-565)", /* VIDEO_PALETTE_RB565 */
- "24-bit RGB", /* VIDEO_PALETTE_RGB24 */
- "32-bit RGB", /* VIDEO_PALETTE_RGB32 */
- "15-bit RGB (RGB-555)", /* VIDEO_PALETTE_RGB555 */
- "YUV-4:2:2 (packed)", /* VIDEO_PALETTE_YUV422 */
- "YUYV", /* VIDEO_PALETTE_YUYV */
- "UYVY", /* VIDEO_PALETTE_UYVY */
- "YUV-4:2:0 (packed)", /* VIDEO_PALETTE_YUV420 */
- "YUV-4:1:1 (packed)", /* VIDEO_PALETTE_YUV411 */
- "Raw", /* VIDEO_PALETTE_RAW */
- "YUV-4:2:2 (planar)", /* VIDEO_PALETTE_YUV422P */
- "YUV-4:1:1 (planar)", /* VIDEO_PALETTE_YUV411P */
- "YUV-4:2:0 (planar)/I420", /* VIDEO_PALETTE_YUV420P */
- "YUV-4:1:0 (planar)" /* VIDEO_PALETTE_YUV410P */
-};
-#endif
-
-/******************************************************
- * gst_v4lsrc_queue_frame():
- * queue a frame for capturing
- * (ie. instruct the hardware to start capture)
- * Requires queue_state lock to be held!
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-static gboolean
-gst_v4lsrc_queue_frame (GstV4lSrc * v4lsrc, gint num)
-{
- GST_LOG_OBJECT (v4lsrc, "queueing frame %d", num);
-
- if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_READY_FOR_QUEUE) {
- return FALSE;
- }
-
- /* instruct the driver to prepare capture using buffer frame num */
- v4lsrc->mmap.frame = num;
- if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd,
- VIDIOCMCAPTURE, &(v4lsrc->mmap)) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL),
- ("Error queueing a buffer (%d): %s", num, g_strerror (errno)));
- return FALSE;
- }
-
- v4lsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED;
- v4lsrc->num_queued++;
-
- return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_hard_sync_frame(GstV4lSrc *v4lsrc,gint num)
- * sync a frame and set the timestamp correctly
- * Requires queue_state lock to be held
- *****************************************************/
-
-static gboolean
-gst_v4lsrc_sync_frame (GstV4lSrc * v4lsrc, gint num)
-{
- GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d", num);
-
- if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_QUEUED) {
- return FALSE;
- }
-
- while (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &num) < 0) {
- /* if the sync() got interrupted, we can retry */
- if (errno != EINTR) {
- v4lsrc->frame_queue_state[num] = QUEUE_STATE_ERROR;
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM);
- return FALSE;
- }
- GST_DEBUG_OBJECT (v4lsrc, "Sync got interrupted");
- }
- GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d done", num);
-
- v4lsrc->frame_queue_state[num] = QUEUE_STATE_SYNCED;
- v4lsrc->num_queued--;
-
- return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_set_capture():
- * set capture parameters, palette = VIDEO_PALETTE_*
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_set_capture (GstV4lSrc * v4lsrc,
- gint width, gint height, gint palette)
-{
- GST_DEBUG_OBJECT (v4lsrc,
- "capture properties set to %dx%d, palette %d", width, height, palette);
-
- v4lsrc->mmap.width = width;
- v4lsrc->mmap.height = height;
- v4lsrc->mmap.format = palette;
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_init():
- * initialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_init (GstV4lSrc * v4lsrc)
-{
- GST_DEBUG_OBJECT (v4lsrc, "initting capture subsystem");
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- /* request the mmap buffer info:
- * total size of mmap buffer, number of frames, offsets of frames */
- if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF,
- &(v4lsrc->mbuf)) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
- ("Error getting buffer information: %s", g_strerror (errno)));
- return FALSE;
- }
-
- if (v4lsrc->mbuf.frames < MIN_BUFFERS_QUEUED) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
- ("Not enough buffers. We got %d, we want at least %d",
- v4lsrc->mbuf.frames, MIN_BUFFERS_QUEUED));
- return FALSE;
- }
-
- GST_INFO_OBJECT (v4lsrc, "Got %d buffers (\'%s\') with total size %d KB",
- v4lsrc->mbuf.frames, v4l_palette_name[v4lsrc->mmap.format],
- v4lsrc->mbuf.size / (v4lsrc->mbuf.frames * 1024));
-
- /* keep track of queued buffers */
- v4lsrc->frame_queue_state = (gint8 *)
- g_malloc (sizeof (gint8) * v4lsrc->mbuf.frames);
-
- /* lock for the frame_state */
- v4lsrc->mutex_queue_state = g_mutex_new ();
- v4lsrc->cond_queue_state = g_cond_new ();
-
- /* Map the buffers */
- GST_V4LELEMENT (v4lsrc)->buffer = mmap (NULL, v4lsrc->mbuf.size,
- PROT_READ | PROT_WRITE, MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
- if (GST_V4LELEMENT (v4lsrc)->buffer == MAP_FAILED) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
- ("Error mapping video buffers: %s", g_strerror (errno)));
- GST_V4LELEMENT (v4lsrc)->buffer = NULL;
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_start():
- * start streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_start (GstV4lSrc * v4lsrc)
-{
- int n;
-
- GST_DEBUG_OBJECT (v4lsrc, "starting capture");
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- g_mutex_lock (v4lsrc->mutex_queue_state);
-
- v4lsrc->quit = FALSE;
- v4lsrc->num_queued = 0;
- v4lsrc->sync_frame = 0;
- v4lsrc->queue_frame = 0;
-
- /* set all buffers ready to queue, and queue captures to the device.
- * This starts streaming capture */
- for (n = 0; n < v4lsrc->mbuf.frames; n++) {
- v4lsrc->frame_queue_state[n] = QUEUE_STATE_READY_FOR_QUEUE;
- if (!gst_v4lsrc_queue_frame (v4lsrc, n)) {
- g_mutex_unlock (v4lsrc->mutex_queue_state);
- gst_v4lsrc_capture_stop (v4lsrc);
- return FALSE;
- }
- }
-
- v4lsrc->is_capturing = TRUE;
- g_mutex_unlock (v4lsrc->mutex_queue_state);
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_grab_frame():
- * capture one frame during streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num)
-{
- GST_LOG_OBJECT (v4lsrc, "grabbing frame %d", *num);
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- g_mutex_lock (v4lsrc->mutex_queue_state);
-
- /* do we have enough frames? */
- while (v4lsrc->num_queued < MIN_BUFFERS_QUEUED ||
- v4lsrc->frame_queue_state[v4lsrc->queue_frame] ==
- QUEUE_STATE_READY_FOR_QUEUE) {
- while (v4lsrc->frame_queue_state[v4lsrc->queue_frame] !=
- QUEUE_STATE_READY_FOR_QUEUE && !v4lsrc->quit) {
- GST_DEBUG_OBJECT (v4lsrc,
- "Waiting for frames to become available (queued %d < minimum %d)",
- v4lsrc->num_queued, MIN_BUFFERS_QUEUED);
- g_cond_wait (v4lsrc->cond_queue_state, v4lsrc->mutex_queue_state);
- }
- if (v4lsrc->quit) {
- g_mutex_unlock (v4lsrc->mutex_queue_state);
- return FALSE;
- }
- if (!gst_v4lsrc_queue_frame (v4lsrc, v4lsrc->queue_frame)) {
- g_mutex_unlock (v4lsrc->mutex_queue_state);
- return FALSE;
- }
- v4lsrc->queue_frame = (v4lsrc->queue_frame + 1) % v4lsrc->mbuf.frames;
- }
-
- /* syncing on the buffer grabs it */
- *num = v4lsrc->sync_frame;
- if (!gst_v4lsrc_sync_frame (v4lsrc, *num)) {
- g_mutex_unlock (v4lsrc->mutex_queue_state);
- return FALSE;
- }
- v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames;
-
- g_mutex_unlock (v4lsrc->mutex_queue_state);
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_get_buffer():
- * get the address of the given frame number in the mmap'd buffer
- * return value: the buffer's address or NULL
- ******************************************************/
-
-guint8 *
-gst_v4lsrc_get_buffer (GstV4lSrc * v4lsrc, gint num)
-{
- if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)) ||
- !GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
- return NULL;
-
- if (num < 0 || num >= v4lsrc->mbuf.frames)
- return NULL;
-
- return GST_V4LELEMENT (v4lsrc)->buffer + v4lsrc->mbuf.offsets[num];
-}
-
-
-/******************************************************
- * gst_v4lsrc_requeue_frame():
- * re-queue a frame after we're done with the buffer
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_requeue_frame (GstV4lSrc * v4lsrc, gint num)
-{
- GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- /* mark frame as 'ready to requeue' */
- g_mutex_lock (v4lsrc->mutex_queue_state);
-
- if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_SYNCED) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, TOO_LAZY, (NULL),
- ("Invalid state %d (expected %d), can't requeue",
- v4lsrc->frame_queue_state[num], QUEUE_STATE_SYNCED));
- return FALSE;
- }
-
- v4lsrc->frame_queue_state[num] = QUEUE_STATE_READY_FOR_QUEUE;
-
- /* let an optional wait know */
- g_cond_broadcast (v4lsrc->cond_queue_state);
-
- g_mutex_unlock (v4lsrc->mutex_queue_state);
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_stop():
- * stop streaming capture
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_stop (GstV4lSrc * v4lsrc)
-{
- GST_DEBUG_OBJECT (v4lsrc, "stopping capture");
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- g_mutex_lock (v4lsrc->mutex_queue_state);
- v4lsrc->is_capturing = FALSE;
-
- /* make an optional pending wait stop */
- v4lsrc->quit = TRUE;
- g_cond_broadcast (v4lsrc->cond_queue_state);
-
- /* sync on remaining frames */
- while (1) {
- if (v4lsrc->frame_queue_state[v4lsrc->sync_frame] == QUEUE_STATE_QUEUED) {
- gst_v4lsrc_sync_frame (v4lsrc, v4lsrc->sync_frame);
- v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames;
- } else {
- break;
- }
- }
-
- g_mutex_unlock (v4lsrc->mutex_queue_state);
-
- return TRUE;
-}
-
-
-/******************************************************
- * gst_v4lsrc_capture_deinit():
- * deinitialize the capture system
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc)
-{
- GST_DEBUG_OBJECT (v4lsrc, "quitting capture subsystem");
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- /* free buffer tracker */
- g_mutex_free (v4lsrc->mutex_queue_state);
- v4lsrc->mutex_queue_state = NULL;
- g_cond_free (v4lsrc->cond_queue_state);
- v4lsrc->cond_queue_state = NULL;
- g_free (v4lsrc->frame_queue_state);
- v4lsrc->frame_queue_state = NULL;
-
- /* unmap the buffer */
- if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, CLOSE, (NULL),
- ("error munmap'ing capture buffer: %s", g_strerror (errno)));
- return FALSE;
- }
- GST_V4LELEMENT (v4lsrc)->buffer = NULL;
-
- return TRUE;
-}
-
-/******************************************************
- * gst_v4lsrc_try_capture():
- * try out a capture on the device
- * This has to be done before initializing the
- * actual capture system, to make sure we don't
- * mess up anything. So we need to mini-mmap()
- * a buffer here, queue and sync on one buffer,
- * and unmap it.
- * This is ugly, yes, I know - but it's a major
- * design flaw of v4l1 that you don't know in
- * advance which formats will be supported...
- * This is better than "just assuming that it'll
- * work"...
- * return value: TRUE on success, FALSE on error
- ******************************************************/
-
-gboolean
-gst_v4lsrc_try_capture (GstV4lSrc * v4lsrc, gint width, gint height,
- gint palette)
-{
- /* so, we need a buffer and some more stuff */
- int frame = 0;
- guint8 *buffer;
- struct video_mbuf vmbuf;
- struct video_mmap vmmap;
-
- GST_DEBUG_OBJECT (v4lsrc, "try out %dx%d, palette format %d (%s)",
- width, height, palette, v4l_palette_name[palette]);
- GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc));
- GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc));
-
- /* let's start by requesting a buffer and mmap()'ing it */
- if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF, &vmbuf) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL),
- ("Error getting buffer information: %s", g_strerror (errno)));
- return FALSE;
- }
- /* Map the buffers */
- buffer = mmap (NULL, vmbuf.size, PROT_READ | PROT_WRITE,
- MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0);
- if (buffer == MAP_FAILED) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL),
- ("Error mapping our try-out buffer: %s", g_strerror (errno)));
- return FALSE;
- }
-
- /* now that we have a buffer, let's try out our format */
- vmmap.width = width;
- vmmap.height = height;
- vmmap.format = palette;
- vmmap.frame = frame;
- if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0) {
- if (errno != EINVAL) /* our format failed! */
- GST_ERROR_OBJECT (v4lsrc,
- "Error queueing our try-out buffer: %s", g_strerror (errno));
- munmap (buffer, vmbuf.size);
- return FALSE;
- }
-
- if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &frame) < 0) {
- GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM);
- munmap (buffer, vmbuf.size);
- return FALSE;
- }
-
- munmap (buffer, vmbuf.size);
-
- /* if we got here, it worked! woohoo, the format is supported! */
- return TRUE;
-}
-
-#ifndef GST_DISABLE_GST_DEBUG
-const char *
-gst_v4lsrc_palette_name (int i)
-{
- return v4l_palette_name[i];
-}
-#endif
-
-gboolean
-gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, gint * fps_n, gint * fps_d)
-{
- gint norm;
- gint fps_index;
- struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
-
- /* check if we have vwin window properties giving a framerate,
- * as is done for webcams
- * See http://www.smcc.demon.nl/webcam/api.html
- * which is used for the Philips and qce-ga drivers */
- fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */
-
- /* webcams have a non-zero fps_index */
- if (fps_index != 0) {
- /* index of 16 corresponds to 15 fps */
- GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
- fps_index * 15, 16, fps_index * 15.0 / 16);
-
- if (fps_n)
- *fps_n = fps_index * 15;
- if (fps_d)
- *fps_d = 16;
-
- return TRUE;
- }
-
- /* removed fps estimation code here */
-
- /* if that failed ... */
-
- if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc)))
- return FALSE;
-
- if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm))
- return FALSE;
-
- if (norm == VIDEO_MODE_NTSC) {
- if (fps_n)
- *fps_n = 30000;
- if (fps_d)
- *fps_d = 1001;
- } else {
- if (fps_n)
- *fps_n = 25;
- if (fps_d)
- *fps_d = 1;
- }
-
- return TRUE;
-}
-
-/* get a list of possible framerates
- * this is only done for webcams;
- * other devices return NULL here.
- * this function takes a LONG time to execute.
- */
-GValue *
-gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc)
-{
- gint fps_index;
- struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
- GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc);
-
- /* check if we have vwin window properties giving a framerate,
- * as is done for webcams
- * See http://www.smcc.demon.nl/webcam/api.html
- * which is used for the Philips and qce-ga drivers */
- fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */
-
- /* webcams have a non-zero fps_index */
- if (fps_index == 0) {
- GST_DEBUG_OBJECT (v4lsrc, "fps_index is 0, no webcam");
- return NULL;
- }
- GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index);
-
- {
- int i;
- GValue *list = NULL;
- GValue value = { 0 };
-
- /* webcam detected, so try all framerates and return a list */
-
- list = g_new0 (GValue, 1);
- g_value_init (list, GST_TYPE_LIST);
-
- /* index of 16 corresponds to 15 fps */
- GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)",
- fps_index * 15, 16, fps_index * 15.0 / 16);
- for (i = 0; i < 63; ++i) {
- /* set bits 16 to 21 to 0 */
- vwin->flags &= (0x3F00 - 1);
- /* set bits 16 to 21 to the index */
- vwin->flags |= i << 16;
- if (gst_v4l_set_window_properties (v4lelement)) {
- /* setting it succeeded. FIXME: get it and check. */
- g_value_init (&value, GST_TYPE_FRACTION);
- gst_value_set_fraction (&value, i * 15, 16);
- gst_value_list_append_value (list, &value);
- g_value_unset (&value);
- }
- }
- /* FIXME: set back the original fps_index */
- vwin->flags &= (0x3F00 - 1);
- vwin->flags |= fps_index << 16;
- gst_v4l_set_window_properties (v4lelement);
- return list;
- }
- return NULL;
-}
-
-#define GST_TYPE_V4LSRC_BUFFER (gst_v4lsrc_buffer_get_type())
-#define GST_IS_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4LSRC_BUFFER))
-#define GST_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4LSRC_BUFFER, GstV4lSrcBuffer))
-
-typedef struct _GstV4lSrcBuffer
-{
- GstBuffer buffer;
-
- GstV4lSrc *v4lsrc;
-
- gint num;
-} GstV4lSrcBuffer;
-
-static void gst_v4lsrc_buffer_class_init (gpointer g_class,
- gpointer class_data);
-static void gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class);
-static void gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer);
-
-static GstBufferClass *v4lbuffer_parent_class = NULL;
-
-static GType
-gst_v4lsrc_buffer_get_type (void)
-{
- static GType _gst_v4lsrc_buffer_type;
-
- if (G_UNLIKELY (_gst_v4lsrc_buffer_type == 0)) {
- static const GTypeInfo v4lsrc_buffer_info = {
- sizeof (GstBufferClass),
- NULL,
- NULL,
- gst_v4lsrc_buffer_class_init,
- NULL,
- NULL,
- sizeof (GstV4lSrcBuffer),
- 0,
- gst_v4lsrc_buffer_init,
- NULL
- };
- _gst_v4lsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
- "GstV4lSrcBuffer", &v4lsrc_buffer_info, 0);
- }
- return _gst_v4lsrc_buffer_type;
-}
-
-static void
-gst_v4lsrc_buffer_class_init (gpointer g_class, gpointer class_data)
-{
- GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
- v4lbuffer_parent_class = g_type_class_peek_parent (g_class);
-
- mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
- gst_v4lsrc_buffer_finalize;
-}
-
-static void
-gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class)
-{
-
-}
-
-static void
-gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer)
-{
- GstV4lSrc *v4lsrc;
- gint num;
-
- v4lsrc = v4lsrc_buffer->v4lsrc;
- num = v4lsrc_buffer->num;
-
- GST_LOG_OBJECT (v4lsrc, "freeing buffer %p for frame %d", v4lsrc_buffer, num);
-
- /* only requeue if we still have an mmap buffer */
- if (GST_V4LELEMENT (v4lsrc)->buffer) {
- GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num);
- gst_v4lsrc_requeue_frame (v4lsrc, num);
- }
-
- gst_object_unref (v4lsrc);
-
- GST_MINI_OBJECT_CLASS (v4lbuffer_parent_class)->
- finalize (GST_MINI_OBJECT (v4lsrc_buffer));
-}
-
-/* Create a V4lSrc buffer from our mmap'd data area */
-GstBuffer *
-gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
-{
- GstBuffer *buf;
- gint fps_n, fps_d;
- GstClockTime duration, timestamp, latency;
-
- GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
-
- g_return_val_if_fail (gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d), NULL);
-
- buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4LSRC_BUFFER);
-
- GST_V4LSRC_BUFFER (buf)->num = num;
- GST_V4LSRC_BUFFER (buf)->v4lsrc = gst_object_ref (v4lsrc);
-
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
- GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
- GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
- GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
-
- duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
- latency = duration;
-
- timestamp = gst_clock_get_time (GST_ELEMENT_CAST (v4lsrc)->clock);
- timestamp -= gst_element_get_base_time (GST_ELEMENT_CAST (v4lsrc));
- if (timestamp > latency)
- timestamp -= latency;
- else
- timestamp = 0;
-
- GST_BUFFER_TIMESTAMP (buf) = timestamp;
- GST_BUFFER_DURATION (buf) = duration;
-
- /* the negotiate() method already set caps on the source pad */
- gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));
-
- return buf;
-}
--- a/gst_plugins_base/sys/v4l/v4lsrc_calls.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* GStreamer
- *
- * v4lsrc_calls.h: functions for V4L video source
- *
- * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __V4L_SRC_CALLS_H__
-#define __V4L_SRC_CALLS_H__
-
-#include "gstv4lsrc.h"
-#include "v4l_calls.h"
-
-
-G_BEGIN_DECLS
-
-
-/* frame grabbing/capture (palette = VIDEO_PALETTE_* - see videodev.h) */
-gboolean gst_v4lsrc_set_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
-gboolean gst_v4lsrc_capture_init (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_capture_start (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_grab_frame (GstV4lSrc *v4lsrc, gint *num);
-guint8 * gst_v4lsrc_get_buffer (GstV4lSrc *v4lsrc, gint num);
-gboolean gst_v4lsrc_requeue_frame (GstV4lSrc *v4lsrc, gint num);
-gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc);
-gboolean gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, gint *fps_n, gint *fps_d);
-GValue * gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc);
-GstBuffer *gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num);
-
-/* "the ugliest hack ever, now available at your local mirror" */
-gboolean gst_v4lsrc_try_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette);
-
-/* For debug purposes, share the palette names */
-#ifndef GST_DISABLE_GST_DEBUG
-const char *gst_v4lsrc_palette_name (int i);
-#endif
-
-
-G_END_DECLS
-
-
-#endif /* __V4L_SRC_CALLS_H__ */
--- a/gst_plugins_base/sys/v4l/videodev_mjpeg.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/* These are the MJPEG API extensions for the Video4Linux API,
- first introduced by the Iomega Buz driver by Rainer Johanni
- <rainer@johanni.de>
-*/
-
-#ifndef __VIDEODEV_MJPEG_H__
-#define __VIDEODEV_MJPEG_H__
-
-/* This is identical with the mgavideo internal params struct,
- please tell me if you change this struct here ! <gz@lysator.liu.se) */
-struct mjpeg_params
-{
-
- /* The following parameters can only be queried */
-
- int major_version; /* Major version number of driver */
- int minor_version; /* Minor version number of driver */
-
- /* Main control parameters */
-
- int input; /* Input channel: 0 = Composite, 1 = S-VHS */
- int norm; /* Norm: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
- int decimation; /* decimation of captured video,
- enlargement of video played back.
- Valid values are 1, 2, 4 or 0.
- 0 is a special value where the user
- has full control over video scaling */
-
- /* The following parameters only have to be set if decimation==0,
- for other values of decimation they provide the data how the image is captured */
-
- int HorDcm; /* Horizontal decimation: 1, 2 or 4 */
- int VerDcm; /* Vertical decimation: 1 or 2 */
- int TmpDcm; /* Temporal decimation: 1 or 2,
- if TmpDcm==2 in capture every second frame is dropped,
- in playback every frame is played twice */
- int field_per_buff; /* Number of fields per buffer: 1 or 2 */
- int img_x; /* start of image in x direction */
- int img_y; /* start of image in y direction */
- int img_width; /* image width BEFORE decimation,
- must be a multiple of HorDcm*16 */
- int img_height; /* image height BEFORE decimation,
- must be a multiple of VerDcm*8 */
-
- /* --- End of parameters for decimation==0 only --- */
-
- /* JPEG control parameters */
-
- int quality; /* Measure for quality of compressed images.
- Scales linearly with the size of the compressed images.
- Must be beetween 0 and 100, 100 is a compression
- ratio of 1:4 */
-
- int odd_even; /* Which field should come first ???
- This is more aptly named "top_first",
- i.e. (odd_even==1) --> top-field-first */
-
- int APPn; /* Number of APP segment to be written, must be 0..15 */
- int APP_len; /* Length of data in JPEG APPn segment */
- char APP_data[60]; /* Data in the JPEG APPn segment. */
-
- int COM_len; /* Length of data in JPEG COM segment */
- char COM_data[60]; /* Data in JPEG COM segment */
-
- unsigned long jpeg_markers; /* Which markers should go into the JPEG output.
- Unless you exactly know what you do, leave them untouched.
- Inluding less markers will make the resulting code
- smaller, but there will be fewer applications
- which can read it.
- The presence of the APP and COM marker is
- influenced by APP0_len and COM_len ONLY! */
-#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
-#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
-#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
-#define JPEG_MARKER_COM (1<<6) /* Comment segment */
-#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */
-
- int VFIFO_FB; /* Flag for enabling Video Fifo Feedback.
- If this flag is turned on and JPEG decompressing
- is going to the screen, the decompress process
- is stopped every time the Video Fifo is full.
- This enables a smooth decompress to the screen
- but the video output signal will get scrambled */
-
- /* Misc */
-
- char reserved[312]; /* Makes 512 bytes for this structure */
-};
-
-struct mjpeg_requestbuffers
-{
- unsigned long count; /* Number of buffers for MJPEG grabbing */
- unsigned long size; /* Size PER BUFFER in bytes */
-};
-
-struct mjpeg_sync
-{
- unsigned long frame; /* Frame (0 - n) for double buffer */
- unsigned long length; /* number of code bytes in buffer (capture only) */
- unsigned long seq; /* frame sequence number */
- struct timeval timestamp; /* timestamp */
-};
-
-struct mjpeg_status
-{
- int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */
- int signal; /* Returned: 1 if valid video signal detected */
- int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */
- int color; /* Returned: 1 if color signal detected */
-};
-
-/*
-Private IOCTL to set up for displaying MJPEG
-*/
-#define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params)
-#define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params)
-#define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers)
-#define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int)
-#define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int)
-#define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync)
-#define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status)
-
-#endif /* __VIDEODEV_MJPEG_H__ */
--- a/gst_plugins_base/sys/ximage/ximage.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* GStreamer
- * Copyright (C) <2003> Julien Moutte <julien@moutte.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ximagesink.h"
-
-GST_DEBUG_CATEGORY (gst_debug_ximagesink);
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "ximagesink",
- GST_RANK_SECONDARY, GST_TYPE_XIMAGESINK))
- return FALSE;
-
- GST_DEBUG_CATEGORY_INIT (gst_debug_ximagesink, "ximagesink", 0,
- "ximagesink element");
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "ximagesink",
- "X11 video output element based on standard Xlib calls",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/ximage/ximagesink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2324 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-ximagesink
- *
- * <refsect2>
- * <para>
- * XImageSink renders video frames to a drawable (XWindow) on a local or remote
- * display. This element can receive a Window ID from the application through
- * the XOverlay interface and will then render video frames in this drawable.
- * If no Window ID was provided by the application, the element will create its
- * own internal window and render into it.
- * </para>
- * <title>Scaling</title>
- * <para>
- * As standard XImage rendering to a drawable is not scaled, XImageSink will use
- * reverse caps negotiation to try to get scaled video frames for the drawable.
- * This is accomplished by asking the peer pad if it accepts some different caps
- * which in most cases implies that there is a scaling element in the pipeline,
- * or that an element generating the video frames can generate them with a
- * different geometry. This mechanism is handled during buffer allocations, for
- * each allocation request the video sink will check the drawable geometry, look
- * at the
- * <link linkend="GstXImageSink--force-aspect-ratio">force-aspect-ratio</link>
- * property, calculate the geometry of desired video frames and then check that
- * the peer pad accept those new caps. If it does it will then allocate a buffer
- * in video memory with this new geometry and return it with the new caps.
- * </para>
- * <title>Events</title>
- * <para>
- * XImageSink creates a thread to handle events coming from the drawable. There
- * are several kind of events that can be grouped in 2 big categories: input
- * events and window state related events. Input events will be translated to
- * navigation events and pushed upstream for other elements to react on them.
- * This includes events such as pointer moves, key press/release, clicks etc...
- * Other events are used to handle the drawable appearance even when the data
- * is not flowing (GST_STATE_PAUSED). That means that even when the element is
- * paused, it will receive expose events from the drawable and draw the latest
- * frame with correct borders/aspect-ratio.
- * </para>
- * <title>Pixel aspect ratio</title>
- * <para>
- * When changing state to GST_STATE_READY, XImageSink will open a connection to
- * the display specified in the
- * <link linkend="GstXImageSink--display">display</link> property or the default
- * display if nothing specified. Once this connection is open it will inspect
- * the display configuration including the physical display geometry and
- * then calculate the pixel aspect ratio. When caps negotiation will occur, the
- * video sink will set the calculated pixel aspect ratio on the caps to make
- * sure that incoming video frames will have the correct pixel aspect ratio for
- * this display. Sometimes the calculated pixel aspect ratio can be wrong, it is
- * then possible to enforce a specific pixel aspect ratio using the
- * <link linkend="GstXImageSink--pixel-aspect-ratio">pixel-aspect-ratio</link>
- * property.
- * </para>
- * <title>Examples</title>
- * <para>
- * Here is a simple pipeline to test reverse negotiation :
- * <programlisting>
- * gst-launch -v videotestsrc ! queue ! ximagesink
- * </programlisting>
- * When the test video signal appears you can resize the window and see that
- * scaled buffers of the desired size are going to arrive with a short delay.
- * This illustrates how buffers of desired size are allocated along the way.
- * If you take away the queue, scaling will happen almost immediately.
- * </para>
- * <para>
- * Here is a simple pipeline to test navigation events :
- * <programlisting>
- * gst-launch -v videotestsrc ! navigationtest ! ffmpegcolorspace ! ximagesink
- * </programlisting>
- * While moving the mouse pointer over the test signal you will see a black box
- * following the mouse pointer. If you press the mouse button somewhere on the
- * video and release it somewhere else a green box will appear where you pressed
- * the button and a red one where you released it. (The navigationtest element
- * is part of gst-plugins-good.)
- * </para>
- * <para>
- * Here is a simple pipeline to test pixel aspect ratio :
- * <programlisting>
- * gst-launch -v videotestsrc ! video/x-raw-rgb, pixel-aspect-ratio=(fraction)4/3 ! videoscale ! ximagesink
- * </programlisting>
- * This is faking a 4/3 pixel aspect ratio caps on video frames produced by
- * videotestsrc, in most cases the pixel aspect ratio of the display will be
- * 1/1. This means that videoscale will have to do the scaling to convert
- * incoming frames to a size that will match the display pixel aspect ratio
- * (from 320x240 to 320x180 in this case). Note that you might have to escape
- * some characters for your shell like '\(fraction\)'.
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Our interfaces */
-#include <gst/interfaces/navigation.h>
-#include <gst/interfaces/xoverlay.h>
-
-/* Object header */
-#include "ximagesink.h"
-
-/* Debugging category */
-#include <gst/gstinfo.h>
-
-GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagesink);
-#define GST_CAT_DEFAULT gst_debug_ximagesink
-
-typedef struct
-{
- unsigned long flags;
- unsigned long functions;
- unsigned long decorations;
- long input_mode;
- unsigned long status;
-}
-MotifWmHints, MwmHints;
-
-#define MWM_HINTS_DECORATIONS (1L << 1)
-
-static void gst_ximagesink_reset (GstXImageSink * ximagesink);
-static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
- GstXImageBuffer * ximage);
-static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink,
- GstXWindow * xwindow);
-static void gst_ximagesink_expose (GstXOverlay * overlay);
-
-/* ElementFactory information */
-static const GstElementDetails gst_ximagesink_details =
-GST_ELEMENT_DETAILS ("Video sink",
- "Sink/Video",
- "A standard X based videosink",
- "Julien Moutte <julien@moutte.net>");
-
-static GstStaticPadTemplate gst_ximagesink_sink_template_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-rgb, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
- );
-
-enum
-{
- PROP_0,
- PROP_DISPLAY,
- PROP_SYNCHRONOUS,
- PROP_PIXEL_ASPECT_RATIO,
- PROP_FORCE_ASPECT_RATIO,
- PROP_HANDLE_EVENTS,
- PROP_HANDLE_EXPOSE
-};
-
-static GstVideoSinkClass *parent_class = NULL;
-
-/* ============================================================= */
-/* */
-/* Private Methods */
-/* */
-/* ============================================================= */
-
-/* ximage buffers */
-
-static GstBufferClass *ximage_buffer_parent_class = NULL;
-
-#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type())
-
-#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER))
-#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer))
-#define GST_XIMAGE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass))
-
-/* So some words about GstMiniObject, this is pretty messy...
- GstMiniObject does not use the standard finalizing of GObjects, you are
- supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref
- which will handle its own refcount system and call gst_mini_object_free.
- gst_mini_object_free will call the class finalize method which is not the
- one from GObject, after calling this finalize method it will free the object
- instance for you if the refcount is still 0 so you should not chain up */
-static void
-gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
-{
- GstXImageSink *ximagesink = NULL;
- gboolean recycled = FALSE;
- gboolean running;
-
- g_return_if_fail (ximage != NULL);
-
- ximagesink = ximage->ximagesink;
- if (G_UNLIKELY (ximagesink == NULL)) {
- GST_WARNING_OBJECT (ximagesink, "no sink found");
- goto beach;
- }
-
- GST_OBJECT_LOCK (ximagesink);
- running = ximagesink->running;
- GST_OBJECT_UNLOCK (ximagesink);
-
- if (running == FALSE) {
- /* If the sink is shutting down, need to clear the image */
- GST_DEBUG_OBJECT (ximagesink,
- "destroy image %p because the sink is shutting down", ximage);
- gst_ximagesink_ximage_destroy (ximagesink, ximage);
- } else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
- (ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
- /* If our geometry changed we can't reuse that image. */
- GST_DEBUG_OBJECT (ximagesink,
- "destroy image %p as its size changed %dx%d vs current %dx%d",
- ximage, ximage->width, ximage->height,
- GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
- gst_ximagesink_ximage_destroy (ximagesink, ximage);
- } else {
- /* In that case we can reuse the image and add it to our image pool. */
- GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
- /* need to increment the refcount again to recycle */
- gst_buffer_ref (GST_BUFFER_CAST (ximage));
- g_mutex_lock (ximagesink->pool_lock);
- ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
- g_mutex_unlock (ximagesink->pool_lock);
- recycled = TRUE;
- }
-
- if (!recycled)
- GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->
- finalize (GST_MINI_OBJECT (ximage));
-
-beach:
- return;
-}
-
-static void
-gst_ximage_buffer_free (GstXImageBuffer * ximage)
-{
- /* make sure it is not recycled */
- ximage->width = -1;
- ximage->height = -1;
- gst_buffer_unref (GST_BUFFER_CAST (ximage));
-}
-
-static void
-gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
-{
-#ifdef HAVE_XSHM
- ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
- ximage_buffer->SHMInfo.shmid = -1;
-#endif
-}
-
-static void
-gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
-{
- GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
- ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
- mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
- gst_ximage_buffer_finalize;
-}
-
-static GType
-gst_ximage_buffer_get_type (void)
-{
- static GType _gst_ximage_buffer_type;
-
- if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) {
- static const GTypeInfo ximage_buffer_info = {
- sizeof (GstBufferClass),
- NULL,
- NULL,
- gst_ximage_buffer_class_init,
- NULL,
- NULL,
- sizeof (GstXImageBuffer),
- 0,
- (GInstanceInitFunc) gst_ximage_buffer_init,
- NULL
- };
- _gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
- "GstXImageBuffer", &ximage_buffer_info, 0);
- }
- return _gst_ximage_buffer_type;
-}
-
-/* X11 stuff */
-
-static gboolean error_caught = FALSE;
-
-static int
-gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
-{
- char error_msg[1024];
-
- XGetErrorText (display, xevent->error_code, error_msg, 1024);
- GST_DEBUG ("ximagesink triggered an XError. error: %s", error_msg);
- error_caught = TRUE;
- return 0;
-}
-
-#ifdef HAVE_XSHM /* Check that XShm calls actually work */
-
-static gboolean
-gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
- GstXContext * xcontext)
-{
- XImage *ximage;
- XShmSegmentInfo SHMInfo;
- size_t size;
- int (*handler) (Display *, XErrorEvent *);
- gboolean result = FALSE;
- gboolean did_attach = FALSE;
-
- g_return_val_if_fail (xcontext != NULL, FALSE);
-
- /* Sync to ensure any older errors are already processed */
- XSync (xcontext->disp, FALSE);
-
- /* Set defaults so we don't free these later unnecessarily */
- SHMInfo.shmaddr = ((void *) -1);
- SHMInfo.shmid = -1;
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
-
- /* Trying to create a 1x1 ximage */
- GST_DEBUG ("XShmCreateImage of 1x1");
-
- ximage = XShmCreateImage (xcontext->disp, xcontext->visual,
- xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1);
-
- /* Might cause an error, sync to ensure it is noticed */
- XSync (xcontext->disp, FALSE);
- if (!ximage || error_caught) {
- GST_WARNING ("could not XShmCreateImage a 1x1 image");
- goto beach;
- }
- size = ximage->height * ximage->bytes_per_line;
-
- SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
- if (SHMInfo.shmid == -1) {
- GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
- size);
- goto beach;
- }
-
- SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
- if (SHMInfo.shmaddr == ((void *) -1)) {
- GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
- /* Clean up shm seg */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
- goto beach;
- }
-
- /* Delete the shared memory segment as soon as we manage to attach.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-
- ximage->data = SHMInfo.shmaddr;
- SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
- GST_WARNING ("Failed to XShmAttach");
- goto beach;
- }
-
- /* Sync to ensure we see any errors we caused */
- XSync (xcontext->disp, FALSE);
-
- if (!error_caught) {
- did_attach = TRUE;
- /* store whether we succeeded in result */
- result = TRUE;
- }
-
-beach:
- /* Sync to ensure we swallow any errors we caused and reset error_caught */
- XSync (xcontext->disp, FALSE);
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- if (did_attach) {
- XShmDetach (xcontext->disp, &SHMInfo);
- XSync (xcontext->disp, FALSE);
- }
- if (SHMInfo.shmaddr != ((void *) -1))
- shmdt (SHMInfo.shmaddr);
- if (ximage)
- XDestroyImage (ximage);
- return result;
-}
-#endif /* HAVE_XSHM */
-
-/* This function handles GstXImageBuffer creation depending on XShm availability */
-static GstXImageBuffer *
-gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
-{
- GstXImageBuffer *ximage = NULL;
- GstStructure *structure = NULL;
- gboolean succeeded = FALSE;
- int (*handler) (Display *, XErrorEvent *);
-
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
- ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER);
-
- structure = gst_caps_get_structure (caps, 0);
-
- if (!gst_structure_get_int (structure, "width", &ximage->width) ||
- !gst_structure_get_int (structure, "height", &ximage->height)) {
- GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
- }
-
- GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage,
- ximage->width, ximage->height);
-
- g_mutex_lock (ximagesink->x_lock);
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_ximagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
- if (ximagesink->xcontext->use_xshm) {
- ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
- ximagesink->xcontext->visual,
- ximagesink->xcontext->depth,
- ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
- if (!ximage->ximage || error_caught) {
- g_mutex_unlock (ximagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximage->width, ximage->height),
- ("could not XShmCreateImage a %dx%d image",
- ximage->width, ximage->height));
- goto beach;
- }
-
- /* we have to use the returned bytes_per_line for our shm size */
- ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
- GST_LOG_OBJECT (ximagesink,
- "XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
- ximage->size, ximage->width, ximage->ximage->bytes_per_line);
-
- ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
- IPC_CREAT | 0777);
- if (ximage->SHMInfo.shmid == -1) {
- g_mutex_unlock (ximagesink->x_lock);
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximage->width, ximage->height),
- ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
- ximage->size));
- goto beach;
- }
-
- ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0);
- if (ximage->SHMInfo.shmaddr == ((void *) -1)) {
- g_mutex_unlock (ximagesink->x_lock);
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximage->width, ximage->height),
- ("Failed to shmat: %s", g_strerror (errno)));
- /* Clean up the shared memory segment */
- shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
- goto beach;
- }
-
- /* Now that we've attached, we can delete the shared memory segment.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
-
- ximage->ximage->data = ximage->SHMInfo.shmaddr;
- ximage->SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) {
- g_mutex_unlock (ximagesink->x_lock);
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximage->width, ximage->height), ("Failed to XShmAttach"));
- goto beach;
- }
-
- XSync (ximagesink->xcontext->disp, FALSE);
- } else
-#endif /* HAVE_XSHM */
- {
- guint allocsize;
-
- ximage->ximage = XCreateImage (ximagesink->xcontext->disp,
- ximagesink->xcontext->visual,
- ximagesink->xcontext->depth,
- ZPixmap, 0, NULL,
- ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
- if (!ximage->ximage || error_caught) {
- g_mutex_unlock (ximagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximage->width, ximage->height),
- ("could not XCreateImage a %dx%d image",
- ximage->width, ximage->height));
- goto beach;
- }
-
- /* upstream will assume that rowstrides are multiples of 4, but this
- * doesn't always seem to be the case with XCreateImage() */
- if ((ximage->ximage->bytes_per_line % 4) != 0) {
- GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
- "usually assumed");
- }
-
- /* we have to use the returned bytes_per_line for our image size */
- ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
-
- /* alloc a bit more for unexpected strides to avoid crashes upstream.
- * FIXME: if we get an unrounded stride, the image will be displayed
- * distorted, since all upstream elements assume a rounded stride */
- allocsize =
- GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) *
- ximage->ximage->height;
- ximage->ximage->data = g_malloc (allocsize);
- GST_LOG_OBJECT (ximagesink,
- "non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
- "stride %d", ximage->size, allocsize, ximage->width,
- ximage->ximage->bytes_per_line);
-
- XSync (ximagesink->xcontext->disp, FALSE);
- }
-
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- succeeded = TRUE;
-
- GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
- GST_BUFFER_SIZE (ximage) = ximage->size;
-
- /* Keep a ref to our sink */
- ximage->ximagesink = gst_object_ref (ximagesink);
-
- g_mutex_unlock (ximagesink->x_lock);
-beach:
- if (!succeeded) {
- gst_ximage_buffer_free (ximage);
- ximage = NULL;
- }
-
- return ximage;
-}
-
-/* This function destroys a GstXImageBuffer handling XShm availability */
-static void
-gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
- GstXImageBuffer * ximage)
-{
- g_return_if_fail (ximage != NULL);
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- /* Hold the object lock to ensure the XContext doesn't disappear */
- GST_OBJECT_LOCK (ximagesink);
-
- /* If the destroyed image is the current one we destroy our reference too */
- if (ximagesink->cur_image == ximage) {
- ximagesink->cur_image = NULL;
- }
-
- /* We might have some buffers destroyed after changing state to NULL */
- if (!ximagesink->xcontext) {
- GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
-#ifdef HAVE_XSHM
- if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
- shmdt (ximage->SHMInfo.shmaddr);
- }
-#endif
- goto beach;
- }
-
- g_mutex_lock (ximagesink->x_lock);
-
-#ifdef HAVE_XSHM
- if (ximagesink->xcontext->use_xshm) {
- if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
- XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
- XSync (ximagesink->xcontext->disp, 0);
- shmdt (ximage->SHMInfo.shmaddr);
- }
- if (ximage->ximage)
- XDestroyImage (ximage->ximage);
-
- } else
-#endif /* HAVE_XSHM */
- {
- if (ximage->ximage) {
- XDestroyImage (ximage->ximage);
- }
- }
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-
-beach:
- GST_OBJECT_UNLOCK (ximagesink);
-
- if (ximage->ximagesink) {
- /* Release the ref to our sink */
- ximage->ximagesink = NULL;
- gst_object_unref (ximagesink);
- }
-
- return;
-}
-
-/* We are called with the x_lock taken */
-static void
-gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
- GstXWindow * xwindow, GstVideoRectangle rect)
-{
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
- g_return_if_fail (xwindow != NULL);
-
- XSetForeground (ximagesink->xcontext->disp, xwindow->gc,
- ximagesink->xcontext->black);
-
- /* Left border */
- if (rect.x > 0) {
- XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, rect.x, xwindow->height);
- }
-
- /* Right border */
- if ((rect.x + rect.w) < xwindow->width) {
- XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
- rect.x + rect.w, 0, xwindow->width, xwindow->height);
- }
-
- /* Top border */
- if (rect.y > 0) {
- XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, xwindow->width, rect.y);
- }
-
- /* Bottom border */
- if ((rect.y + rect.h) < xwindow->height) {
- XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, rect.y + rect.h, xwindow->width, xwindow->height);
- }
-}
-
-/* This function puts a GstXImageBuffer on a GstXImageSink's window */
-static gboolean
-gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
-{
- GstVideoRectangle src, dst, result;
- gboolean draw_border = FALSE;
-
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
-
- /* We take the flow_lock. If expose is in there we don't want to run
- concurrently from the data flow thread */
- g_mutex_lock (ximagesink->flow_lock);
-
- if (G_UNLIKELY (ximagesink->xwindow == NULL)) {
- g_mutex_unlock (ximagesink->flow_lock);
- return FALSE;
- }
-
- /* Draw borders when displaying the first frame. After this
- draw borders only on expose event. */
- if (!ximagesink->cur_image) {
- draw_border = TRUE;
- }
-
- /* Store a reference to the last image we put, lose the previous one */
- if (ximage && ximagesink->cur_image != ximage) {
- if (ximagesink->cur_image) {
- GST_LOG_OBJECT (ximagesink, "unreffing %p", ximagesink->cur_image);
- gst_buffer_unref (ximagesink->cur_image);
- }
- GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
- ximagesink->cur_image =
- GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage)));
- }
-
- /* Expose sends a NULL image, we take the latest frame */
- if (!ximage) {
- draw_border = TRUE;
- if (ximagesink->cur_image) {
- ximage = ximagesink->cur_image;
- } else {
- g_mutex_unlock (ximagesink->flow_lock);
- return TRUE;
- }
- }
-
- gst_ximagesink_xwindow_update_geometry (ximagesink, ximagesink->xwindow);
-
- src.w = ximage->width;
- src.h = ximage->height;
- dst.w = ximagesink->xwindow->width;
- dst.h = ximagesink->xwindow->height;
-
- gst_video_sink_center_rect (src, dst, &result, FALSE);
-
- g_mutex_lock (ximagesink->x_lock);
-
- if (draw_border) {
- gst_ximagesink_xwindow_draw_borders (ximagesink, ximagesink->xwindow,
- result);
- }
-#ifdef HAVE_XSHM
- if (ximagesink->xcontext->use_xshm) {
- GST_LOG_OBJECT (ximagesink,
- "XShmPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d",
- ximage, 0, 0, result.x, result.y, result.w, result.h,
- ximagesink->xwindow->width, ximagesink->xwindow->height);
- XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
- ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
- result.w, result.h, FALSE);
- } else
-#endif /* HAVE_XSHM */
- {
- GST_LOG_OBJECT (ximagesink,
- "XPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d",
- ximage, 0, 0, result.x, result.y, result.w, result.h,
- ximagesink->xwindow->width, ximagesink->xwindow->height);
- XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
- ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
- result.w, result.h);
- }
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-
- g_mutex_unlock (ximagesink->flow_lock);
-
- return TRUE;
-}
-
-static gboolean
-gst_ximagesink_xwindow_decorate (GstXImageSink * ximagesink,
- GstXWindow * window)
-{
- Atom hints_atom = None;
- MotifWmHints *hints;
-
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
- g_return_val_if_fail (window != NULL, FALSE);
-
- g_mutex_lock (ximagesink->x_lock);
-
- hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS", 1);
- if (hints_atom == None) {
- g_mutex_unlock (ximagesink->x_lock);
- return FALSE;
- }
-
- hints = g_malloc0 (sizeof (MotifWmHints));
-
- hints->flags |= MWM_HINTS_DECORATIONS;
- hints->decorations = 1 << 0;
-
- XChangeProperty (ximagesink->xcontext->disp, window->win,
- hints_atom, hints_atom, 32, PropModeReplace,
- (guchar *) hints, sizeof (MotifWmHints) / sizeof (long));
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-
- g_free (hints);
-
- return TRUE;
-}
-
-/* This function handles a GstXWindow creation */
-static GstXWindow *
-gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
-{
- GstXWindow *xwindow = NULL;
- XGCValues values;
-
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
- xwindow = g_new0 (GstXWindow, 1);
-
- xwindow->width = width;
- xwindow->height = height;
- xwindow->internal = TRUE;
-
- g_mutex_lock (ximagesink->x_lock);
-
- xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
- ximagesink->xcontext->root,
- 0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black);
-
- /* We have to do that to prevent X from redrawing the background on
- ConfigureNotify. This takes away flickering of video when resizing. */
- XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None);
-
- if (ximagesink->handle_events) {
- Atom wm_delete;
-
- XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
- StructureNotifyMask | PointerMotionMask | KeyPressMask |
- KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-
- /* Tell the window manager we'd like delete client messages instead of
- * being killed */
- wm_delete = XInternAtom (ximagesink->xcontext->disp,
- "WM_DELETE_WINDOW", False);
- (void) XSetWMProtocols (ximagesink->xcontext->disp, xwindow->win,
- &wm_delete, 1);
- }
-
- xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win,
- 0, &values);
-
- XMapRaised (ximagesink->xcontext->disp, xwindow->win);
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-
- gst_ximagesink_xwindow_decorate (ximagesink, xwindow);
-
- gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (ximagesink), xwindow->win);
-
- return xwindow;
-}
-
-/* This function destroys a GstXWindow */
-static void
-gst_ximagesink_xwindow_destroy (GstXImageSink * ximagesink,
- GstXWindow * xwindow)
-{
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- g_mutex_lock (ximagesink->x_lock);
-
- /* If we did not create that window we just free the GC and let it live */
- if (xwindow->internal)
- XDestroyWindow (ximagesink->xcontext->disp, xwindow->win);
- else
- XSelectInput (ximagesink->xcontext->disp, xwindow->win, 0);
-
- XFreeGC (ximagesink->xcontext->disp, xwindow->gc);
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-
- g_free (xwindow);
-}
-
-static void
-gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink,
- GstXWindow * xwindow)
-{
- XWindowAttributes attr;
-
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- /* Update the window geometry */
- g_mutex_lock (ximagesink->x_lock);
-
- XGetWindowAttributes (ximagesink->xcontext->disp,
- ximagesink->xwindow->win, &attr);
-
- ximagesink->xwindow->width = attr.width;
- ximagesink->xwindow->height = attr.height;
-
- g_mutex_unlock (ximagesink->x_lock);
-}
-
-static void
-gst_ximagesink_xwindow_clear (GstXImageSink * ximagesink, GstXWindow * xwindow)
-{
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- g_mutex_lock (ximagesink->x_lock);
-
- XSetForeground (ximagesink->xcontext->disp, xwindow->gc,
- ximagesink->xcontext->black);
-
- XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, xwindow->width, xwindow->height);
-
- XSync (ximagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (ximagesink->x_lock);
-}
-
-/* This function handles XEvents that might be in the queue. It generates
- GstEvent that will be sent upstream in the pipeline to handle interactivity
- and navigation.*/
-static void
-gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
-{
- XEvent e;
- guint pointer_x = 0, pointer_y = 0;
- gboolean pointer_moved = FALSE;
- gboolean exposed = FALSE, configured = FALSE;
-
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- /* Then we get all pointer motion events, only the last position is
- interesting. */
- g_mutex_lock (ximagesink->flow_lock);
- g_mutex_lock (ximagesink->x_lock);
- while (XCheckWindowEvent (ximagesink->xcontext->disp,
- ximagesink->xwindow->win, PointerMotionMask, &e)) {
- g_mutex_unlock (ximagesink->x_lock);
- g_mutex_unlock (ximagesink->flow_lock);
-
- switch (e.type) {
- case MotionNotify:
- pointer_x = e.xmotion.x;
- pointer_y = e.xmotion.y;
- pointer_moved = TRUE;
- break;
- default:
- break;
- }
- g_mutex_lock (ximagesink->flow_lock);
- g_mutex_lock (ximagesink->x_lock);
- }
-
- if (pointer_moved) {
- g_mutex_unlock (ximagesink->x_lock);
- g_mutex_unlock (ximagesink->flow_lock);
-
- GST_DEBUG ("ximagesink pointer moved over window at %d,%d",
- pointer_x, pointer_y);
- gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
- "mouse-move", 0, pointer_x, pointer_y);
-
- g_mutex_lock (ximagesink->flow_lock);
- g_mutex_lock (ximagesink->x_lock);
- }
-
- /* We get all remaining events on our window to throw them upstream */
- while (XCheckWindowEvent (ximagesink->xcontext->disp,
- ximagesink->xwindow->win,
- KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask, &e)) {
- KeySym keysym;
-
- /* We lock only for the X function call */
- g_mutex_unlock (ximagesink->x_lock);
- g_mutex_unlock (ximagesink->flow_lock);
-
- switch (e.type) {
- case ButtonPress:
- /* Mouse button pressed/released over our window. We send upstream
- events for interactivity/navigation */
- GST_DEBUG ("ximagesink button %d pressed over window at %d,%d",
- e.xbutton.button, e.xbutton.x, e.xbutton.x);
- gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
- "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
- break;
- case ButtonRelease:
- GST_DEBUG ("ximagesink button %d release over window at %d,%d",
- e.xbutton.button, e.xbutton.x, e.xbutton.x);
- gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink),
- "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
- break;
- case KeyPress:
- case KeyRelease:
- /* Key pressed/released over our window. We send upstream
- events for interactivity/navigation */
- GST_DEBUG ("ximagesink key %d pressed over window at %d,%d",
- e.xkey.keycode, e.xkey.x, e.xkey.x);
- g_mutex_lock (ximagesink->x_lock);
- keysym = XKeycodeToKeysym (ximagesink->xcontext->disp,
- e.xkey.keycode, 0);
- g_mutex_unlock (ximagesink->x_lock);
- if (keysym != NoSymbol) {
- char *key_str = NULL;
-
- g_mutex_lock (ximagesink->x_lock);
- key_str = XKeysymToString (keysym);
- g_mutex_unlock (ximagesink->x_lock);
- gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
- e.type == KeyPress ? "key-press" : "key-release", key_str);
-
- } else {
- gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
- e.type == KeyPress ? "key-press" : "key-release", "unknown");
- }
- break;
- default:
- GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)",
- e.type);
- }
- g_mutex_lock (ximagesink->flow_lock);
- g_mutex_lock (ximagesink->x_lock);
- }
-
- while (XCheckWindowEvent (ximagesink->xcontext->disp,
- ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
- switch (e.type) {
- case Expose:
- exposed = TRUE;
- break;
- case ConfigureNotify:
- configured = TRUE;
- break;
- default:
- break;
- }
- }
-
- if (ximagesink->handle_expose && (exposed || configured)) {
- g_mutex_unlock (ximagesink->x_lock);
- g_mutex_unlock (ximagesink->flow_lock);
-
- gst_ximagesink_expose (GST_X_OVERLAY (ximagesink));
-
- g_mutex_lock (ximagesink->flow_lock);
- g_mutex_lock (ximagesink->x_lock);
- }
-
- /* Handle Display events */
- while (XPending (ximagesink->xcontext->disp)) {
- XNextEvent (ximagesink->xcontext->disp, &e);
-
- switch (e.type) {
- case ClientMessage:{
- Atom wm_delete;
-
- wm_delete = XInternAtom (ximagesink->xcontext->disp,
- "WM_DELETE_WINDOW", False);
- if (wm_delete == (Atom) e.xclient.data.l[0]) {
- /* Handle window deletion by posting an error on the bus */
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, NOT_FOUND,
- ("Output window was closed"), (NULL));
-
- g_mutex_unlock (ximagesink->x_lock);
- gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
- ximagesink->xwindow = NULL;
- g_mutex_lock (ximagesink->x_lock);
- }
- break;
- }
- default:
- break;
- }
- }
-
- g_mutex_unlock (ximagesink->x_lock);
- g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static gpointer
-gst_ximagesink_event_thread (GstXImageSink * ximagesink)
-{
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
- GST_OBJECT_LOCK (ximagesink);
- while (ximagesink->running) {
- GST_OBJECT_UNLOCK (ximagesink);
-
- if (ximagesink->xwindow) {
- gst_ximagesink_handle_xevents (ximagesink);
- }
- g_usleep (100000);
-
- GST_OBJECT_LOCK (ximagesink);
- }
- GST_OBJECT_UNLOCK (ximagesink);
-
- return NULL;
-}
-
-/* This function calculates the pixel aspect ratio based on the properties
- * in the xcontext structure and stores it there. */
-static void
-gst_ximagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
-{
- static const gint par[][2] = {
- {1, 1}, /* regular screen */
- {16, 15}, /* PAL TV */
- {11, 10}, /* 525 line Rec.601 video */
- {54, 59}, /* 625 line Rec.601 video */
- {64, 45}, /* 1280x1024 on 16:9 display */
- {5, 3}, /* 1280x1024 on 4:3 display */
- {4, 3} /* 800x600 on 16:9 display */
- };
- gint i;
- gint index;
- gdouble ratio;
- gdouble delta;
-
-#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
-
- /* first calculate the "real" ratio based on the X values;
- * which is the "physical" w/h divided by the w/h in pixels of the display */
- ratio = (gdouble) (xcontext->widthmm * xcontext->height)
- / (xcontext->heightmm * xcontext->width);
-
- /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
- * override here */
- if (xcontext->width == 720 && xcontext->height == 576) {
- ratio = 4.0 * 576 / (3.0 * 720);
- }
- GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
-
- /* now find the one from par[][2] with the lowest delta to the real one */
- delta = DELTA (0);
- index = 0;
-
- for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
- gdouble this_delta = DELTA (i);
-
- if (this_delta < delta) {
- index = i;
- delta = this_delta;
- }
- }
-
- GST_DEBUG ("Decided on index %d (%d/%d)", index,
- par[index][0], par[index][1]);
-
- g_free (xcontext->par);
- xcontext->par = g_new0 (GValue, 1);
- g_value_init (xcontext->par, GST_TYPE_FRACTION);
- gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
- GST_DEBUG ("set xcontext PAR to %d/%d",
- gst_value_get_fraction_numerator (xcontext->par),
- gst_value_get_fraction_denominator (xcontext->par));
-}
-
-/* This function gets the X Display and global info about it. Everything is
- stored in our object and will be cleaned when the object is disposed. Note
- here that caps for supported format are generated without any window or
- image creation */
-static GstXContext *
-gst_ximagesink_xcontext_get (GstXImageSink * ximagesink)
-{
- GstXContext *xcontext = NULL;
- XPixmapFormatValues *px_formats = NULL;
- gint nb_formats = 0, i;
-
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
-
- xcontext = g_new0 (GstXContext, 1);
-
- g_mutex_lock (ximagesink->x_lock);
-
- xcontext->disp = XOpenDisplay (ximagesink->display_name);
-
- if (!xcontext->disp) {
- g_mutex_unlock (ximagesink->x_lock);
- g_free (xcontext);
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Could not initialise X output"), ("Could not open display"));
- return NULL;
- }
-
- xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
- xcontext->screen_num = DefaultScreen (xcontext->disp);
- xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
- xcontext->root = DefaultRootWindow (xcontext->disp);
- xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
- xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
- xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
-
- xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
- xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
- xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
- xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
-
- GST_DEBUG_OBJECT (ximagesink, "X reports %dx%d pixels and %d mm x %d mm",
- xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
-
- gst_ximagesink_calculate_pixel_aspect_ratio (xcontext);
-
- /* We get supported pixmap formats at supported depth */
- px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
-
- if (!px_formats) {
- XCloseDisplay (xcontext->disp);
- g_mutex_unlock (ximagesink->x_lock);
- g_free (xcontext->par);
- g_free (xcontext);
- return NULL;
- }
-
- /* We get bpp value corresponding to our running depth */
- for (i = 0; i < nb_formats; i++) {
- if (px_formats[i].depth == xcontext->depth)
- xcontext->bpp = px_formats[i].bits_per_pixel;
- }
-
- XFree (px_formats);
-
- xcontext->endianness =
- (ImageByteOrder (xcontext->disp) ==
- LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
-
- /* Search for XShm extension support */
-#ifdef HAVE_XSHM
- if (XShmQueryExtension (xcontext->disp) &&
- gst_ximagesink_check_xshm_calls (ximagesink, xcontext)) {
- xcontext->use_xshm = TRUE;
- GST_DEBUG ("ximagesink is using XShm extension");
- } else
-#endif
- {
- xcontext->use_xshm = FALSE;
- GST_DEBUG ("ximagesink is not using XShm extension");
- }
-
- /* our caps system handles 24/32bpp RGB as big-endian. */
- if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
- xcontext->endianness == G_LITTLE_ENDIAN) {
- xcontext->endianness = G_BIG_ENDIAN;
- xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
- xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
- xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
- if (xcontext->bpp == 24) {
- xcontext->visual->red_mask >>= 8;
- xcontext->visual->green_mask >>= 8;
- xcontext->visual->blue_mask >>= 8;
- }
- }
-
- /* update object's par with calculated one if not set yet */
- if (!ximagesink->par) {
- ximagesink->par = g_new0 (GValue, 1);
- gst_value_init_and_copy (ximagesink->par, xcontext->par);
- GST_DEBUG_OBJECT (ximagesink, "set calculated PAR on object's PAR");
- }
- xcontext->caps = gst_caps_new_simple ("video/x-raw-rgb",
- "bpp", G_TYPE_INT, xcontext->bpp,
- "depth", G_TYPE_INT, xcontext->depth,
- "endianness", G_TYPE_INT, xcontext->endianness,
- "red_mask", G_TYPE_INT, xcontext->visual->red_mask,
- "green_mask", G_TYPE_INT, xcontext->visual->green_mask,
- "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask,
- "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
- "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
- if (ximagesink->par) {
- int nom, den;
-
- nom = gst_value_get_fraction_numerator (ximagesink->par);
- den = gst_value_get_fraction_denominator (ximagesink->par);
- gst_caps_set_simple (xcontext->caps, "pixel-aspect-ratio",
- GST_TYPE_FRACTION, nom, den, NULL);
- }
-
- g_mutex_unlock (ximagesink->x_lock);
-
- /* Setup our event listening thread */
- GST_OBJECT_LOCK (ximagesink);
- ximagesink->running = TRUE;
- ximagesink->event_thread = g_thread_create (
- (GThreadFunc) gst_ximagesink_event_thread, ximagesink, TRUE, NULL);
- GST_OBJECT_UNLOCK (ximagesink);
-
- return xcontext;
-}
-
-/* This function cleans the X context. Closing the Display and unrefing the
- caps for supported formats. */
-static void
-gst_ximagesink_xcontext_clear (GstXImageSink * ximagesink)
-{
- GstXContext *xcontext;
-
- g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
-
- GST_OBJECT_LOCK (ximagesink);
- if (ximagesink->xcontext == NULL) {
- GST_OBJECT_UNLOCK (ximagesink);
- return;
- }
-
- /* Take the xcontext reference and NULL it while we
- * clean it up, so that any buffer-alloced buffers
- * arriving after this will be freed correctly */
- xcontext = ximagesink->xcontext;
- ximagesink->xcontext = NULL;
-
- GST_OBJECT_UNLOCK (ximagesink);
-
- gst_caps_unref (xcontext->caps);
- g_free (xcontext->par);
- g_free (ximagesink->par);
- ximagesink->par = NULL;
-
- g_mutex_lock (ximagesink->x_lock);
-
- XCloseDisplay (xcontext->disp);
-
- g_mutex_unlock (ximagesink->x_lock);
-
- g_free (xcontext);
-}
-
-static void
-gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
-{
-
- g_mutex_lock (ximagesink->pool_lock);
-
- while (ximagesink->buffer_pool) {
- GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
-
- ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
- ximagesink->buffer_pool);
- gst_ximage_buffer_free (ximage);
- }
-
- g_mutex_unlock (ximagesink->pool_lock);
-}
-
-/* Element stuff */
-
-static GstCaps *
-gst_ximagesink_getcaps (GstBaseSink * bsink)
-{
- GstXImageSink *ximagesink;
- GstCaps *caps;
- int i;
-
- ximagesink = GST_XIMAGESINK (bsink);
-
- if (ximagesink->xcontext)
- return gst_caps_ref (ximagesink->xcontext->caps);
-
- /* get a template copy and add the pixel aspect ratio */
- caps =
- gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK (ximagesink)->
- sinkpad));
- for (i = 0; i < gst_caps_get_size (caps); ++i) {
- GstStructure *structure = gst_caps_get_structure (caps, i);
-
- if (ximagesink->par) {
- int nom, den;
-
- nom = gst_value_get_fraction_numerator (ximagesink->par);
- den = gst_value_get_fraction_denominator (ximagesink->par);
- gst_structure_set (structure, "pixel-aspect-ratio",
- GST_TYPE_FRACTION, nom, den, NULL);
- }
- }
-
- return caps;
-}
-
-static gboolean
-gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
-{
- GstXImageSink *ximagesink;
- gboolean ret = TRUE;
- GstStructure *structure;
- GstCaps *intersection;
- const GValue *par;
- gint new_width, new_height;
- const GValue *fps;
-
- ximagesink = GST_XIMAGESINK (bsink);
-
- if (!ximagesink->xcontext)
- return FALSE;
-
- GST_DEBUG_OBJECT (ximagesink,
- "sinkconnect possible caps %" GST_PTR_FORMAT " with given caps %"
- GST_PTR_FORMAT, ximagesink->xcontext->caps, caps);
-
- /* We intersect those caps with our template to make sure they are correct */
- intersection = gst_caps_intersect (ximagesink->xcontext->caps, caps);
- GST_DEBUG_OBJECT (ximagesink, "intersection returned %" GST_PTR_FORMAT,
- intersection);
- if (gst_caps_is_empty (intersection)) {
- gst_caps_unref (intersection);
- return FALSE;
- }
-
- gst_caps_unref (intersection);
-
- structure = gst_caps_get_structure (caps, 0);
-
- ret &= gst_structure_get_int (structure, "width", &new_width);
- ret &= gst_structure_get_int (structure, "height", &new_height);
- fps = gst_structure_get_value (structure, "framerate");
- ret &= (fps != NULL);
- if (!ret)
- return FALSE;
-
- /* if the caps contain pixel-aspect-ratio, they have to match ours,
- * otherwise linking should fail */
- par = gst_structure_get_value (structure, "pixel-aspect-ratio");
- if (par) {
- if (ximagesink->par) {
- if (gst_value_compare (par, ximagesink->par) != GST_VALUE_EQUAL) {
- goto wrong_aspect;
- }
- } else if (ximagesink->xcontext->par) {
- if (gst_value_compare (par, ximagesink->xcontext->par) != GST_VALUE_EQUAL) {
- goto wrong_aspect;
- }
- }
- }
-
- GST_VIDEO_SINK_WIDTH (ximagesink) = new_width;
- GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height;
- ximagesink->fps_n = gst_value_get_fraction_numerator (fps);
- ximagesink->fps_d = gst_value_get_fraction_denominator (fps);
-
- /* Notify application to set xwindow id now */
- g_mutex_lock (ximagesink->flow_lock);
- if (!ximagesink->xwindow) {
- g_mutex_unlock (ximagesink->flow_lock);
- gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink));
- } else {
- g_mutex_unlock (ximagesink->flow_lock);
- }
-
- /* Creating our window and our image */
- if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 ||
- GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0) {
- GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL),
- ("Invalid image size."));
- return FALSE;
- }
-
- g_mutex_lock (ximagesink->flow_lock);
- if (!ximagesink->xwindow) {
- ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink,
- GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
- }
- g_mutex_unlock (ximagesink->flow_lock);
-
- /* If our ximage has changed we destroy it, next chain iteration will create
- a new one */
- if ((ximagesink->ximage) &&
- ((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) ||
- (GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) {
- GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
- ximagesink->ximage);
- gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
- ximagesink->ximage = NULL;
- }
-
- return TRUE;
-
- /* ERRORS */
-wrong_aspect:
- {
- GST_INFO_OBJECT (ximagesink, "pixel aspect ratio does not match");
- return FALSE;
- }
-}
-
-static GstStateChangeReturn
-gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
-{
- GstXImageSink *ximagesink;
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstXContext *xcontext = NULL;
-
- ximagesink = GST_XIMAGESINK (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
-
- /* Initializing the XContext */
- if (ximagesink->xcontext == NULL) {
- xcontext = gst_ximagesink_xcontext_get (ximagesink);
- if (xcontext == NULL) {
- ret = GST_STATE_CHANGE_FAILURE;
- goto beach;
- }
- GST_OBJECT_LOCK (ximagesink);
- if (xcontext)
- ximagesink->xcontext = xcontext;
- GST_OBJECT_UNLOCK (ximagesink);
- }
-
- /* call XSynchronize with the current value of synchronous */
- GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
- ximagesink->synchronous ? "TRUE" : "FALSE");
- g_mutex_lock (ximagesink->x_lock);
- XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
- g_mutex_unlock (ximagesink->x_lock);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- g_mutex_lock (ximagesink->flow_lock);
- if (ximagesink->xwindow)
- gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
- g_mutex_unlock (ximagesink->flow_lock);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- ximagesink->fps_n = 0;
- ximagesink->fps_d = 1;
- GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
- GST_VIDEO_SINK_HEIGHT (ximagesink) = 0;
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_ximagesink_reset (ximagesink);
- break;
- default:
- break;
- }
-
-beach:
- return ret;
-}
-
-static void
-gst_ximagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
- GstClockTime * start, GstClockTime * end)
-{
- GstXImageSink *ximagesink;
-
- ximagesink = GST_XIMAGESINK (bsink);
-
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- *start = GST_BUFFER_TIMESTAMP (buf);
- if (GST_BUFFER_DURATION_IS_VALID (buf)) {
- *end = *start + GST_BUFFER_DURATION (buf);
- } else {
- if (ximagesink->fps_n > 0) {
- *end = *start +
- gst_util_uint64_scale_int (GST_SECOND, ximagesink->fps_d,
- ximagesink->fps_n);
- }
- }
- }
-}
-
-static GstFlowReturn
-gst_ximagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
- GstXImageSink *ximagesink;
-
- g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
- ximagesink = GST_XIMAGESINK (bsink);
-
- /* If this buffer has been allocated using our buffer management we simply
- put the ximage which is in the PRIVATE pointer */
- if (GST_IS_XIMAGE_BUFFER (buf)) {
- GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
- if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
- goto no_window;
- } else {
- /* Else we have to copy the data into our private image, */
- /* if we have one... */
- GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
- if (!ximagesink->ximage) {
- GST_DEBUG_OBJECT (ximagesink, "creating our ximage");
- ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink,
- GST_BUFFER_CAPS (buf));
- if (!ximagesink->ximage)
- /* The create method should have posted an informative error */
- goto no_ximage;
-
- if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) {
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- ximagesink->ximage->width, ximagesink->ximage->height),
- ("XServer allocated buffer size did not match input buffer"));
-
- gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
- ximagesink->ximage = NULL;
- goto no_ximage;
- }
- }
- memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
- MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
- if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
- goto no_window;
- }
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-no_ximage:
- {
- /* No image available. That's very bad ! */
- GST_DEBUG ("could not create image");
- return GST_FLOW_ERROR;
- }
-no_window:
- {
- /* No Window available to put our image into */
- GST_WARNING_OBJECT (ximagesink, "could not output image - no window");
- return GST_FLOW_ERROR;
- }
-}
-
-/* Buffer management
- *
- * The buffer_alloc function must either return a buffer with given size and
- * caps or create a buffer with different caps attached to the buffer. This
- * last option is called reverse negotiation, ie, where the sink suggests a
- * different format from the upstream peer.
- *
- * We try to do reverse negotiation when our geometry changes and we like a
- * resized buffer.
- */
-static GstFlowReturn
-gst_ximagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
- GstCaps * caps, GstBuffer ** buf)
-{
- GstXImageSink *ximagesink;
- GstXImageBuffer *ximage = NULL;
- GstStructure *structure = NULL;
- GstFlowReturn ret = GST_FLOW_OK;
- GstCaps *alloc_caps;
- gboolean alloc_unref = FALSE;
- gint width, height;
-
- ximagesink = GST_XIMAGESINK (bsink);
-
- GST_LOG_OBJECT (ximagesink,
- "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT
- " and offset %" G_GUINT64_FORMAT, size, caps, offset);
-
- /* assume we're going to alloc what was requested, keep track of
- * wheter we need to unref or not. When we suggest a new format
- * upstream we will create a new caps that we need to unref. */
- alloc_caps = caps;
- alloc_unref = FALSE;
-
- /* get struct to see what is requested */
- structure = gst_caps_get_structure (caps, 0);
-
- if (gst_structure_get_int (structure, "width", &width) &&
- gst_structure_get_int (structure, "height", &height)) {
- GstVideoRectangle dst, src, result;
-
- src.w = width;
- src.h = height;
-
- /* We take the flow_lock because the window might go away */
- g_mutex_lock (ximagesink->flow_lock);
- if (!ximagesink->xwindow) {
- g_mutex_unlock (ximagesink->flow_lock);
- goto alloc;
- }
-
- /* What is our geometry */
- gst_ximagesink_xwindow_update_geometry (ximagesink, ximagesink->xwindow);
- dst.w = ximagesink->xwindow->width;
- dst.h = ximagesink->xwindow->height;
-
- g_mutex_unlock (ximagesink->flow_lock);
-
- if (ximagesink->keep_aspect) {
- GST_LOG_OBJECT (ximagesink, "enforcing aspect ratio in reverse caps "
- "negotiation");
- gst_video_sink_center_rect (src, dst, &result, TRUE);
- } else {
- GST_LOG_OBJECT (ximagesink, "trying to resize to window geometry "
- "ignoring aspect ratio");
- result.x = result.y = 0;
- result.w = dst.w;
- result.h = dst.h;
- }
-
- /* We would like another geometry */
- if (width != result.w || height != result.h) {
- int nom, den;
- GstCaps *desired_caps;
- GstStructure *desired_struct;
-
- /* make a copy of the incomming caps to create the new
- * suggestion. We can't use make_writable because we might
- * then destroy the original caps which we still need when the
- * peer does not accept the suggestion. */
- desired_caps = gst_caps_copy (caps);
- desired_struct = gst_caps_get_structure (desired_caps, 0);
-
- GST_DEBUG ("we would love to receive a %dx%d video", result.w, result.h);
- gst_structure_set (desired_struct, "width", G_TYPE_INT, result.w, NULL);
- gst_structure_set (desired_struct, "height", G_TYPE_INT, result.h, NULL);
-
- /* PAR property overrides the X calculated one */
- if (ximagesink->par) {
- nom = gst_value_get_fraction_numerator (ximagesink->par);
- den = gst_value_get_fraction_denominator (ximagesink->par);
- gst_structure_set (desired_struct, "pixel-aspect-ratio",
- GST_TYPE_FRACTION, nom, den, NULL);
- } else if (ximagesink->xcontext->par) {
- nom = gst_value_get_fraction_numerator (ximagesink->xcontext->par);
- den = gst_value_get_fraction_denominator (ximagesink->xcontext->par);
- gst_structure_set (desired_struct, "pixel-aspect-ratio",
- GST_TYPE_FRACTION, nom, den, NULL);
- }
-
- /* see if peer accepts our new suggestion, if there is no peer, this
- * function returns true. */
- if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (ximagesink),
- desired_caps)) {
- gint bpp;
-
- bpp = size / height / width;
- /* we will not alloc a buffer of the new suggested caps. Make sure
- * we also unref this new caps after we set it on the buffer. */
- alloc_caps = desired_caps;
- alloc_unref = TRUE;
- width = result.w;
- height = result.h;
- size = bpp * width * height;
- GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT
- " buffer size is now %d bytes", desired_caps, size);
- } else {
- GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT,
- desired_caps);
- /* we alloc a buffer with the original incomming caps */
- width = GST_VIDEO_SINK_WIDTH (ximagesink);
- height = GST_VIDEO_SINK_HEIGHT (ximagesink);
- }
- }
- }
-
-alloc:
- /* Inspect our buffer pool */
- g_mutex_lock (ximagesink->pool_lock);
- while (ximagesink->buffer_pool) {
- ximage = (GstXImageBuffer *) ximagesink->buffer_pool->data;
-
- if (ximage) {
- /* Removing from the pool */
- ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
- ximagesink->buffer_pool);
-
- /* If the ximage is invalid for our need, destroy */
- if ((ximage->width != width) || (ximage->height != height)) {
- gst_ximage_buffer_free (ximage);
- ximage = NULL;
- } else {
- /* We found a suitable ximage */
- break;
- }
- }
- }
- g_mutex_unlock (ximagesink->pool_lock);
-
- /* We haven't found anything, creating a new one */
- if (!ximage) {
- ximage = gst_ximagesink_ximage_new (ximagesink, alloc_caps);
- }
- /* Now we should have a ximage, set appropriate caps on it */
- if (ximage) {
- gst_buffer_set_caps (GST_BUFFER_CAST (ximage), alloc_caps);
- }
-
- /* could be our new reffed suggestion or the original unreffed caps */
- if (alloc_unref)
- gst_caps_unref (alloc_caps);
-
- *buf = GST_BUFFER_CAST (ximage);
-
- return ret;
-}
-
-/* Interfaces stuff */
-
-static gboolean
-gst_ximagesink_interface_supported (GstImplementsInterface * iface, GType type)
-{
- g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY);
- return TRUE;
-}
-
-static void
-gst_ximagesink_interface_init (GstImplementsInterfaceClass * klass)
-{
- klass->supported = gst_ximagesink_interface_supported;
-}
-
-static void
-gst_ximagesink_navigation_send_event (GstNavigation * navigation,
- GstStructure * structure)
-{
- GstXImageSink *ximagesink = GST_XIMAGESINK (navigation);
- GstEvent *event;
- gint x_offset, y_offset;
- gdouble x, y;
- GstPad *pad = NULL;
-
- event = gst_event_new_navigation (structure);
-
- /* We are not converting the pointer coordinates as there's no hardware
- scaling done here. The only possible scaling is done by videoscale and
- videoscale will have to catch those events and tranform the coordinates
- to match the applied scaling. So here we just add the offset if the image
- is centered in the window. */
-
- /* We take the flow_lock while we look at the window */
- g_mutex_lock (ximagesink->flow_lock);
-
- if (!ximagesink->xwindow) {
- g_mutex_unlock (ximagesink->flow_lock);
- return;
- }
-
- x_offset = ximagesink->xwindow->width - GST_VIDEO_SINK_WIDTH (ximagesink);
- y_offset = ximagesink->xwindow->height - GST_VIDEO_SINK_HEIGHT (ximagesink);
-
- g_mutex_unlock (ximagesink->flow_lock);
-
- if (gst_structure_get_double (structure, "pointer_x", &x)) {
- x -= x_offset / 2;
- gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL);
- }
- if (gst_structure_get_double (structure, "pointer_y", &y)) {
- y -= y_offset / 2;
- gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL);
- }
-
- pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (ximagesink));
-
- if (GST_IS_PAD (pad) && GST_IS_EVENT (event)) {
- gst_pad_send_event (pad, event);
-
- gst_object_unref (pad);
- }
-}
-
-static void
-gst_ximagesink_navigation_init (GstNavigationInterface * iface)
-{
- iface->send_event = gst_ximagesink_navigation_send_event;
-}
-
-static void
-gst_ximagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
- GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
- GstXWindow *xwindow = NULL;
- XWindowAttributes attr;
-
- /* We acquire the stream lock while setting this window in the element.
- We are basically cleaning tons of stuff replacing the old window, putting
- images while we do that would surely crash */
- g_mutex_lock (ximagesink->flow_lock);
-
- /* If we already use that window return */
- if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win)) {
- g_mutex_unlock (ximagesink->flow_lock);
- return;
- }
-
- /* If the element has not initialized the X11 context try to do so */
- if (!ximagesink->xcontext &&
- !(ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink))) {
- g_mutex_unlock (ximagesink->flow_lock);
- /* we have thrown a GST_ELEMENT_ERROR now */
- return;
- }
-
- /* If a window is there already we destroy it */
- if (ximagesink->xwindow) {
- gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
- ximagesink->xwindow = NULL;
- }
-
- /* If the xid is 0 we go back to an internal window */
- if (xwindow_id == 0) {
- /* If no width/height caps nego did not happen window will be created
- during caps nego then */
- if (GST_VIDEO_SINK_WIDTH (ximagesink) && GST_VIDEO_SINK_HEIGHT (ximagesink)) {
- xwindow = gst_ximagesink_xwindow_new (ximagesink,
- GST_VIDEO_SINK_WIDTH (ximagesink),
- GST_VIDEO_SINK_HEIGHT (ximagesink));
- }
- } else {
- xwindow = g_new0 (GstXWindow, 1);
-
- xwindow->win = xwindow_id;
-
- /* We get window geometry, set the event we want to receive,
- and create a GC */
- g_mutex_lock (ximagesink->x_lock);
- XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr);
- xwindow->width = attr.width;
- xwindow->height = attr.height;
- xwindow->internal = FALSE;
- if (ximagesink->handle_events) {
- XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask |
- StructureNotifyMask | PointerMotionMask | KeyPressMask |
- KeyReleaseMask);
- }
-
- xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, 0, NULL);
- g_mutex_unlock (ximagesink->x_lock);
- }
-
- if (xwindow)
- ximagesink->xwindow = xwindow;
-
- g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static void
-gst_ximagesink_expose (GstXOverlay * overlay)
-{
- GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
-
- gst_ximagesink_ximage_put (ximagesink, NULL);
-}
-
-static void
-gst_ximagesink_set_event_handling (GstXOverlay * overlay,
- gboolean handle_events)
-{
- GstXImageSink *ximagesink = GST_XIMAGESINK (overlay);
-
- ximagesink->handle_events = handle_events;
-
- g_mutex_lock (ximagesink->flow_lock);
-
- if (G_UNLIKELY (!ximagesink->xwindow)) {
- g_mutex_unlock (ximagesink->flow_lock);
- return;
- }
-
- g_mutex_lock (ximagesink->x_lock);
-
- if (handle_events) {
- if (ximagesink->xwindow->internal) {
- XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
- ExposureMask | StructureNotifyMask | PointerMotionMask |
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
- } else {
- XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win,
- ExposureMask | StructureNotifyMask | PointerMotionMask |
- KeyPressMask | KeyReleaseMask);
- }
- } else {
- XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, 0);
- }
-
- g_mutex_unlock (ximagesink->x_lock);
-
- g_mutex_unlock (ximagesink->flow_lock);
-}
-
-static void
-gst_ximagesink_xoverlay_init (GstXOverlayClass * iface)
-{
- iface->set_xwindow_id = gst_ximagesink_set_xwindow_id;
- iface->expose = gst_ximagesink_expose;
- iface->handle_events = gst_ximagesink_set_event_handling;
-}
-
-/* =========================================== */
-/* */
-/* Init & Class init */
-/* */
-/* =========================================== */
-
-static void
-gst_ximagesink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstXImageSink *ximagesink;
-
- g_return_if_fail (GST_IS_XIMAGESINK (object));
-
- ximagesink = GST_XIMAGESINK (object);
-
- switch (prop_id) {
- case PROP_DISPLAY:
- ximagesink->display_name = g_strdup (g_value_get_string (value));
- break;
- case PROP_SYNCHRONOUS:
- ximagesink->synchronous = g_value_get_boolean (value);
- if (ximagesink->xcontext) {
- GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s",
- ximagesink->synchronous ? "TRUE" : "FALSE");
- g_mutex_lock (ximagesink->x_lock);
- XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous);
- g_mutex_unlock (ximagesink->x_lock);
- }
- break;
- case PROP_FORCE_ASPECT_RATIO:
- ximagesink->keep_aspect = g_value_get_boolean (value);
- break;
- case PROP_PIXEL_ASPECT_RATIO:
- {
- GValue *tmp;
-
- tmp = g_new0 (GValue, 1);
- g_value_init (tmp, GST_TYPE_FRACTION);
-
- if (!g_value_transform (value, tmp)) {
- GST_WARNING_OBJECT (ximagesink,
- "Could not transform string to aspect ratio");
- g_free (tmp);
- } else {
- GST_DEBUG_OBJECT (ximagesink, "set PAR to %d/%d",
- gst_value_get_fraction_numerator (tmp),
- gst_value_get_fraction_denominator (tmp));
- g_free (ximagesink->par);
- ximagesink->par = tmp;
- }
- }
- break;
- case PROP_HANDLE_EVENTS:
- gst_ximagesink_set_event_handling (GST_X_OVERLAY (ximagesink),
- g_value_get_boolean (value));
- break;
- case PROP_HANDLE_EXPOSE:
- ximagesink->handle_expose = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_ximagesink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstXImageSink *ximagesink;
-
- g_return_if_fail (GST_IS_XIMAGESINK (object));
-
- ximagesink = GST_XIMAGESINK (object);
-
- switch (prop_id) {
- case PROP_DISPLAY:
- g_value_set_string (value, ximagesink->display_name);
- break;
- case PROP_SYNCHRONOUS:
- g_value_set_boolean (value, ximagesink->synchronous);
- break;
- case PROP_FORCE_ASPECT_RATIO:
- g_value_set_boolean (value, ximagesink->keep_aspect);
- break;
- case PROP_PIXEL_ASPECT_RATIO:
- if (ximagesink->par)
- g_value_transform (ximagesink->par, value);
- break;
- case PROP_HANDLE_EVENTS:
- g_value_set_boolean (value, ximagesink->handle_events);
- break;
- case PROP_HANDLE_EXPOSE:
- g_value_set_boolean (value, ximagesink->handle_expose);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_ximagesink_reset (GstXImageSink * ximagesink)
-{
- GThread *thread;
-
- GST_OBJECT_LOCK (ximagesink);
- ximagesink->running = FALSE;
- /* grab thread and mark it as NULL */
- thread = ximagesink->event_thread;
- ximagesink->event_thread = NULL;
- GST_OBJECT_UNLOCK (ximagesink);
-
- /* Wait for our event thread to finish before we clean up our stuff. */
- if (thread)
- g_thread_join (thread);
-
- if (ximagesink->ximage) {
- gst_buffer_unref (ximagesink->ximage);
- ximagesink->ximage = NULL;
- }
- if (ximagesink->cur_image) {
- gst_buffer_unref (ximagesink->cur_image);
- ximagesink->cur_image = NULL;
- }
-
- gst_ximagesink_bufferpool_clear (ximagesink);
-
- g_mutex_lock (ximagesink->flow_lock);
- if (ximagesink->xwindow) {
- gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
- gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
- ximagesink->xwindow = NULL;
- }
- g_mutex_unlock (ximagesink->flow_lock);
-
- gst_ximagesink_xcontext_clear (ximagesink);
-}
-
-static void
-gst_ximagesink_finalize (GObject * object)
-{
- GstXImageSink *ximagesink;
-
- ximagesink = GST_XIMAGESINK (object);
-
- gst_ximagesink_reset (ximagesink);
-
- if (ximagesink->display_name) {
- g_free (ximagesink->display_name);
- ximagesink->display_name = NULL;
- }
- if (ximagesink->par) {
- g_free (ximagesink->par);
- ximagesink->par = NULL;
- }
- if (ximagesink->x_lock) {
- g_mutex_free (ximagesink->x_lock);
- ximagesink->x_lock = NULL;
- }
- if (ximagesink->flow_lock) {
- g_mutex_free (ximagesink->flow_lock);
- ximagesink->flow_lock = NULL;
- }
- if (ximagesink->pool_lock) {
- g_mutex_free (ximagesink->pool_lock);
- ximagesink->pool_lock = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_ximagesink_init (GstXImageSink * ximagesink)
-{
- ximagesink->display_name = NULL;
- ximagesink->xcontext = NULL;
- ximagesink->xwindow = NULL;
- ximagesink->ximage = NULL;
- ximagesink->cur_image = NULL;
-
- ximagesink->event_thread = NULL;
- ximagesink->running = FALSE;
-
- ximagesink->fps_n = 0;
- ximagesink->fps_d = 1;
-
- ximagesink->x_lock = g_mutex_new ();
- ximagesink->flow_lock = g_mutex_new ();
-
- ximagesink->par = NULL;
-
- ximagesink->pool_lock = g_mutex_new ();
- ximagesink->buffer_pool = NULL;
-
- ximagesink->synchronous = FALSE;
- ximagesink->keep_aspect = FALSE;
- ximagesink->handle_events = TRUE;
- ximagesink->handle_expose = TRUE;
-}
-
-static void
-gst_ximagesink_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_ximagesink_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_ximagesink_sink_template_factory));
-}
-
-static void
-gst_ximagesink_class_init (GstXImageSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_ximagesink_finalize;
- gobject_class->set_property = gst_ximagesink_set_property;
- gobject_class->get_property = gst_ximagesink_get_property;
-
- g_object_class_install_property (gobject_class, PROP_DISPLAY,
- g_param_spec_string ("display", "Display", "X Display name",
- NULL, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
- g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs "
- "the X display in synchronous mode. (used only for debugging)", FALSE,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
- g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
- "When enabled, reverse caps negotiation (scaling) will respect "
- "original aspect ratio", FALSE, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
- g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
- "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS,
- g_param_spec_boolean ("handle-events", "Handle XEvents",
- "When enabled, XEvents will be selected and handled", TRUE,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE,
- g_param_spec_boolean ("handle-expose", "Handle expose", "When enabled, "
- "the current frame will always be drawn in response to X Expose "
- "events", TRUE, G_PARAM_READWRITE));
-
- gstelement_class->change_state = gst_ximagesink_change_state;
-
- gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
- gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
- gstbasesink_class->buffer_alloc =
- GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
- gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
- gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
- gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
-}
-
-/* ============================================================= */
-/* */
-/* Public Methods */
-/* */
-/* ============================================================= */
-
-/* =========================================== */
-/* */
-/* Object typing & Creation */
-/* */
-/* =========================================== */
-
-GType
-gst_ximagesink_get_type (void)
-{
- static GType ximagesink_type = 0;
-
- if (!ximagesink_type) {
- static const GTypeInfo ximagesink_info = {
- sizeof (GstXImageSinkClass),
- gst_ximagesink_base_init,
- NULL,
- (GClassInitFunc) gst_ximagesink_class_init,
- NULL,
- NULL,
- sizeof (GstXImageSink),
- 0,
- (GInstanceInitFunc) gst_ximagesink_init,
- };
- static const GInterfaceInfo iface_info = {
- (GInterfaceInitFunc) gst_ximagesink_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo navigation_info = {
- (GInterfaceInitFunc) gst_ximagesink_navigation_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo overlay_info = {
- (GInterfaceInitFunc) gst_ximagesink_xoverlay_init,
- NULL,
- NULL,
- };
-
- ximagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
- "GstXImageSink", &ximagesink_info, 0);
-
- g_type_add_interface_static (ximagesink_type, GST_TYPE_IMPLEMENTS_INTERFACE,
- &iface_info);
- g_type_add_interface_static (ximagesink_type, GST_TYPE_NAVIGATION,
- &navigation_info);
- g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
- &overlay_info);
-
- /* register type and create class in a more safe place instead of at
- * runtime since the type registration and class creation is not
- * threadsafe. */
- g_type_class_ref (gst_ximage_buffer_get_type ());
- }
-
- return ximagesink_type;
-}
--- a/gst_plugins_base/sys/ximage/ximagesink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_XIMAGESINK_H__
-#define __GST_XIMAGESINK_H__
-
-#include <gst/video/gstvideosink.h>
-
-#ifdef HAVE_XSHM
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#ifdef HAVE_XSHM
-#include <X11/extensions/XShm.h>
-#endif /* HAVE_XSHM */
-
-#include <string.h>
-#include <math.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_XIMAGESINK \
- (gst_ximagesink_get_type())
-#define GST_XIMAGESINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XIMAGESINK, GstXImageSink))
-#define GST_XIMAGESINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XIMAGESINK, GstXImageSinkClass))
-#define GST_IS_XIMAGESINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XIMAGESINK))
-#define GST_IS_XIMAGESINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XIMAGESINK))
-
-typedef struct _GstXContext GstXContext;
-typedef struct _GstXWindow GstXWindow;
-
-typedef struct _GstXImageBuffer GstXImageBuffer;
-typedef struct _GstXImageBufferClass GstXImageBufferClass;
-
-typedef struct _GstXImageSink GstXImageSink;
-typedef struct _GstXImageSinkClass GstXImageSinkClass;
-
-/**
- * GstXContext:
- * @disp: the X11 Display of this context
- * @screen: the default Screen of Display @disp
- * @screen_num: the Screen number of @screen
- * @visual: the default Visual of Screen @screen
- * @root: the root Window of Display @disp
- * @white: the value of a white pixel on Screen @screen
- * @black: the value of a black pixel on Screen @screen
- * @depth: the color depth of Display @disp
- * @bpp: the number of bits per pixel on Display @disp
- * @endianness: the endianness of image bytes on Display @disp
- * @width: the width in pixels of Display @disp
- * @height: the height in pixels of Display @disp
- * @widthmm: the width in millimeters of Display @disp
- * @heightmm: the height in millimeters of Display @disp
- * @par: the pixel aspect ratio calculated from @width, @widthmm and @height,
- * @heightmm ratio
- * @use_xshm: used to known wether of not XShm extension is usable or not even
- * if the Extension is present
- * @caps: the #GstCaps that Display @disp can accept
- *
- * Structure used to store various informations collected/calculated for a
- * Display.
- */
-struct _GstXContext {
- Display *disp;
-
- Screen *screen;
- gint screen_num;
-
- Visual *visual;
-
- Window root;
-
- gulong white, black;
-
- gint depth;
- gint bpp;
- gint endianness;
-
- gint width, height;
- gint widthmm, heightmm;
- GValue *par; /* calculated pixel aspect ratio */
-
- gboolean use_xshm;
-
- GstCaps *caps;
-};
-
-/**
- * GstXWindow:
- * @win: the Window ID of this X11 window
- * @width: the width in pixels of Window @win
- * @height: the height in pixels of Window @win
- * @internal: used to remember if Window @win was created internally or passed
- * through the #GstXOverlay interface
- * @gc: the Graphical Context of Window @win
- *
- * Structure used to store informations about a Window.
- */
-struct _GstXWindow {
- Window win;
- gint width, height;
- gboolean internal;
- GC gc;
-};
-
-/**
- * GstXImageBuffer:
- * @ximagesink: a reference to our #GstXImageSink
- * @ximage: the XImage of this buffer
- * @width: the width in pixels of XImage @ximage
- * @height: the height in pixels of XImage @ximage
- * @size: the size in bytes of XImage @ximage
- *
- * Subclass of #GstBuffer containing additional information about an XImage.
- */
-struct _GstXImageBuffer {
- GstBuffer buffer;
-
- /* Reference to the ximagesink we belong to */
- GstXImageSink *ximagesink;
-
- XImage *ximage;
-
-#ifdef HAVE_XSHM
- XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
-
- gint width, height;
- size_t size;
-};
-
-/**
- * GstXImageSink:
- * @display_name: the name of the Display we want to render to
- * @xcontext: our instance's #GstXContext
- * @xwindow: the #GstXWindow we are rendering to
- * @ximage: internal #GstXImage used to store incoming buffers and render when
- * not using the buffer_alloc optimization mechanism
- * @cur_image: a reference to the last #GstXImage that was put to @xwindow. It
- * is used when Expose events are received to redraw the latest video frame
- * @event_thread: a thread listening for events on @xwindow and handling them
- * @running: used to inform @event_thread if it should run/shutdown
- * @fps_n: the framerate fraction numerator
- * @fps_d: the framerate fraction denominator
- * @x_lock: used to protect X calls as we are not using the XLib in threaded
- * mode
- * @flow_lock: used to protect data flow routines from external calls such as
- * events from @event_thread or methods from the #GstXOverlay interface
- * @par: used to override calculated pixel aspect ratio from @xcontext
- * @pool_lock: used to protect the buffer pool
- * @buffer_pool: a list of #GstXImageBuffer that could be reused at next buffer
- * allocation call
- * @synchronous: used to store if XSynchronous should be used or not (for
- * debugging purpose only)
- * @keep_aspect: used to remember if reverse negotiation scaling should respect
- * aspect ratio
- * @handle_events: used to know if we should handle select XEvents or not
- *
- * The #GstXImageSink data structure.
- */
-struct _GstXImageSink {
- /* Our element stuff */
- GstVideoSink videosink;
-
- char *display_name;
-
- GstXContext *xcontext;
- GstXWindow *xwindow;
- GstXImageBuffer *ximage;
- GstXImageBuffer *cur_image;
-
- GThread *event_thread;
- gboolean running;
-
- /* Framerate numerator and denominator */
- gint fps_n;
- gint fps_d;
-
- GMutex *x_lock;
- GMutex *flow_lock;
-
- /* object-set pixel aspect ratio */
- GValue *par;
-
- GMutex *pool_lock;
- GSList *buffer_pool;
-
- gboolean synchronous;
- gboolean keep_aspect;
- gboolean handle_events;
- gboolean handle_expose;
-};
-
-struct _GstXImageSinkClass {
- GstVideoSinkClass parent_class;
-};
-
-GType gst_ximagesink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_XIMAGESINK_H__ */
--- a/gst_plugins_base/sys/xvimage/xvimagesink.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3254 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/**
- * SECTION:element-xvimagesink
- *
- * <refsect2>
- * <para>
- * XvImageSink renders video frames to a drawable (XWindow) on a local display
- * using the XVideo extension. Rendering to a remote display is theorically
- * possible but i doubt that the XVideo extension is actually available when
- * connecting to a remote display. This element can receive a Window ID from the
- * application through the XOverlay interface and will then render video frames
- * in this drawable. If no Window ID was provided by the application, the
- * element will create its own internal window and render into it.
- * </para>
- * <title>Scaling</title>
- * <para>
- * The XVideo extension, when it's available, handles hardware accelerated
- * scaling of video frames. This means that the element will just accept
- * incoming video frames no matter their geometry and will then put them to the
- * drawable scaling them on the fly. Using the
- * <link linkend="GstXvImageSink--force-aspect-ratio">force-aspect-ratio</link>
- * property it is possible to enforce scaling with a constant aspect ratio,
- * which means drawing black borders around the video frame.
- * </para>
- * <title>Events</title>
- * <para>
- * XvImageSink creates a thread to handle events coming from the drawable. There
- * are several kind of events that can be grouped in 2 big categories: input
- * events and window state related events. Input events will be translated to
- * navigation events and pushed upstream for other elements to react on them.
- * This includes events such as pointer moves, key press/release, clicks etc...
- * Other events are used to handle the drawable appearance even when the data
- * is not flowing (GST_STATE_PAUSED). That means that even when the element is
- * paused, it will receive expose events from the drawable and draw the latest
- * frame with correct borders/aspect-ratio.
- * </para>
- * <title>Pixel aspect ratio</title>
- * <para>
- * When changing state to GST_STATE_READY, XvImageSink will open a connection to
- * the display specified in the
- * <link linkend="GstXvImageSink--display">display</link> property or the
- * default display if nothing specified. Once this connection is open it will
- * inspect the display configuration including the physical display geometry and
- * then calculate the pixel aspect ratio. When receiving video frames with a
- * different pixel aspect ratio, XvImageSink will use hardware scaling to
- * display the video frames correctly on display's pixel aspect ratio.
- * Sometimes the calculated pixel aspect ratio can be wrong, it is
- * then possible to enforce a specific pixel aspect ratio using the
- * <link linkend="GstXvImageSink--pixel-aspect-ratio">pixel-aspect-ratio</link>
- * property.
- * </para>
- * <title>Examples</title>
- * <para>
- * Here is a simple pipeline to test hardware scaling :
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink
- * </programlisting>
- * When the test video signal appears you can resize the window and see that
- * video frames are scaled through hardware (no extra CPU cost). You can try
- * again setting the force-aspect-ratio property to true and observe the borders
- * drawn around the scaled image respecting aspect ratio.
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink force-aspect-ratio=true
- * </programlisting>
- * </para>
- * <para>
- * Here is a simple pipeline to test navigation events :
- * <programlisting>
- * gst-launch -v videotestsrc ! navigationtest ! xvimagesink
- * </programlisting>
- * While moving the mouse pointer over the test signal you will see a black box
- * following the mouse pointer. If you press the mouse button somewhere on the
- * video and release it somewhere else a green box will appear where you pressed
- * the button and a red one where you released it. (The navigationtest element
- * is part of gst-plugins-good.) You can observe here that even if the images
- * are scaled through hardware the pointer coordinates are converted back to the
- * original video frame geometry so that the box can be drawn to the correct
- * position. This also handles borders correctly, limiting coordinates to the
- * image area
- * </para>
- * <para>
- * Here is a simple pipeline to test pixel aspect ratio :
- * <programlisting>
- * gst-launch -v videotestsrc ! video/x-raw-yuv, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink
- * </programlisting>
- * This is faking a 4/3 pixel aspect ratio caps on video frames produced by
- * videotestsrc, in most cases the pixel aspect ratio of the display will be
- * 1/1. This means that XvImageSink will have to do the scaling to convert
- * incoming frames to a size that will match the display pixel aspect ratio
- * (from 320x240 to 320x180 in this case). Note that you might have to escape
- * some characters for your shell like '\(fraction\)'.
- * </para>
- * <para>
- * Here is a test pipeline to test the colorbalance interface :
- * <programlisting>
- * gst-launch -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100
- * </programlisting>
- * </para>
- * </refsect2>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Our interfaces */
-#include <gst/interfaces/navigation.h>
-#include <gst/interfaces/xoverlay.h>
-#include <gst/interfaces/colorbalance.h>
-#include <gst/interfaces/propertyprobe.h>
-/* Helper functions */
-#include <gst/video/video.h>
-
-/* Object header */
-#include "xvimagesink.h"
-
-/* Debugging category */
-#include <gst/gstinfo.h>
-GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink);
-#define GST_CAT_DEFAULT gst_debug_xvimagesink
-
-typedef struct
-{
- unsigned long flags;
- unsigned long functions;
- unsigned long decorations;
- long input_mode;
- unsigned long status;
-}
-MotifWmHints, MwmHints;
-
-#define MWM_HINTS_DECORATIONS (1L << 1)
-
-static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
-
-static GstBufferClass *xvimage_buffer_parent_class = NULL;
-static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
-
-static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
- xvimagesink, GstXWindow * xwindow);
-static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
- GstCaps * caps);
-static void gst_xvimagesink_expose (GstXOverlay * overlay);
-
-/* ElementFactory information */
-static const GstElementDetails gst_xvimagesink_details =
-GST_ELEMENT_DETAILS ("Video sink",
- "Sink/Video",
- "A Xv based videosink",
- "Julien Moutte <julien@moutte.net>");
-
-/* Default template - initiated with class struct to allow gst-register to work
- without X running */
-static GstStaticPadTemplate gst_xvimagesink_sink_template_factory =
- GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-rgb, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], "
- "height = (int) [ 1, MAX ]; "
- "video/x-raw-yuv, "
- "framerate = (fraction) [ 0, MAX ], "
- "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
- );
-
-enum
-{
- ARG_0,
- ARG_CONTRAST,
- ARG_BRIGHTNESS,
- ARG_HUE,
- ARG_SATURATION,
- ARG_DISPLAY,
- ARG_SYNCHRONOUS,
- ARG_PIXEL_ASPECT_RATIO,
- ARG_FORCE_ASPECT_RATIO,
- ARG_HANDLE_EVENTS,
- ARG_DEVICE,
- ARG_DEVICE_NAME,
- ARG_HANDLE_EXPOSE,
- ARG_DOUBLE_BUFFER
-};
-
-static GstVideoSinkClass *parent_class = NULL;
-
-/* ============================================================= */
-/* */
-/* Private Methods */
-/* */
-/* ============================================================= */
-
-/* xvimage buffers */
-
-#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type())
-
-#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER))
-#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer))
-
-/* This function destroys a GstXvImage handling XShm availability */
-static void
-gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
-{
- GstXvImageSink *xvimagesink;
-
- GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
-
- xvimagesink = xvimage->xvimagesink;
- if (G_UNLIKELY (xvimagesink == NULL))
- goto no_sink;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- GST_OBJECT_LOCK (xvimagesink);
-
- /* If the destroyed image is the current one we destroy our reference too */
- if (xvimagesink->cur_image == xvimage)
- xvimagesink->cur_image = NULL;
-
- /* We might have some buffers destroyed after changing state to NULL */
- if (xvimagesink->xcontext == NULL) {
- GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
-#ifdef HAVE_XSHM
- /* Need to free the shared memory segment even if the x context
- * was already cleaned up */
- if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
- shmdt (xvimage->SHMInfo.shmaddr);
- }
-#endif
- goto beach;
- }
-
- g_mutex_lock (xvimagesink->x_lock);
-
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
- GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
- xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
- XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo);
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- shmdt (xvimage->SHMInfo.shmaddr);
- }
- if (xvimage->xvimage)
- XFree (xvimage->xvimage);
- } else
-#endif /* HAVE_XSHM */
- {
- if (xvimage->xvimage) {
- if (xvimage->xvimage->data) {
- g_free (xvimage->xvimage->data);
- }
- XFree (xvimage->xvimage);
- }
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
-beach:
- GST_OBJECT_UNLOCK (xvimagesink);
- xvimage->xvimagesink = NULL;
- gst_object_unref (xvimagesink);
-
- GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->
- finalize (GST_MINI_OBJECT (xvimage));
-
- return;
-
-no_sink:
- {
- GST_WARNING ("no sink found");
- return;
- }
-}
-
-static void
-gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
-{
- GstXvImageSink *xvimagesink;
- gboolean running;
-
- xvimagesink = xvimage->xvimagesink;
- if (G_UNLIKELY (xvimagesink == NULL))
- goto no_sink;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- GST_OBJECT_LOCK (xvimagesink);
- running = xvimagesink->running;
- GST_OBJECT_UNLOCK (xvimagesink);
-
- /* If our geometry changed we can't reuse that image. */
- if (running == FALSE) {
- GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
- gst_xvimage_buffer_destroy (xvimage);
- } else if ((xvimage->width != xvimagesink->video_width) ||
- (xvimage->height != xvimagesink->video_height)) {
- GST_LOG_OBJECT (xvimage,
- "destroy image as its size changed %dx%d vs current %dx%d",
- xvimage->width, xvimage->height,
- xvimagesink->video_width, xvimagesink->video_height);
- gst_xvimage_buffer_destroy (xvimage);
- } else {
- /* In that case we can reuse the image and add it to our image pool. */
- GST_LOG_OBJECT (xvimage, "recycling image in pool");
- /* need to increment the refcount again to recycle */
- gst_buffer_ref (GST_BUFFER (xvimage));
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
- xvimage);
- g_mutex_unlock (xvimagesink->pool_lock);
- }
- return;
-
-no_sink:
- {
- GST_WARNING ("no sink found");
- return;
- }
-}
-
-static void
-gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
-{
- /* make sure it is not recycled */
- xvimage->width = -1;
- xvimage->height = -1;
- gst_buffer_unref (GST_BUFFER (xvimage));
-}
-
-static void
-gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
-{
-#ifdef HAVE_XSHM
- xvimage->SHMInfo.shmaddr = ((void *) -1);
- xvimage->SHMInfo.shmid = -1;
-#endif
-}
-
-static void
-gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
-{
- GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
-
- xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
-
- mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
- gst_xvimage_buffer_finalize;
-}
-
-static GType
-gst_xvimage_buffer_get_type (void)
-{
- static GType _gst_xvimage_buffer_type;
-
- if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) {
- static const GTypeInfo xvimage_buffer_info = {
- sizeof (GstBufferClass),
- NULL,
- NULL,
- gst_xvimage_buffer_class_init,
- NULL,
- NULL,
- sizeof (GstXvImageBuffer),
- 0,
- (GInstanceInitFunc) gst_xvimage_buffer_init,
- NULL
- };
- _gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
- "GstXvImageBuffer", &xvimage_buffer_info, 0);
- }
- return _gst_xvimage_buffer_type;
-}
-
-/* X11 stuff */
-
-static gboolean error_caught = FALSE;
-
-static int
-gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
-{
- char error_msg[1024];
-
- XGetErrorText (display, xevent->error_code, error_msg, 1024);
- GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
- error_caught = TRUE;
- return 0;
-}
-
-#ifdef HAVE_XSHM
-/* This function checks that it is actually really possible to create an image
- using XShm */
-static gboolean
-gst_xvimagesink_check_xshm_calls (GstXContext * xcontext)
-{
- XvImage *xvimage;
- XShmSegmentInfo SHMInfo;
- gint size;
- int (*handler) (Display *, XErrorEvent *);
- gboolean result = FALSE;
- gboolean did_attach = FALSE;
-
- g_return_val_if_fail (xcontext != NULL, FALSE);
-
- /* Sync to ensure any older errors are already processed */
- XSync (xcontext->disp, FALSE);
-
- /* Set defaults so we don't free these later unnecessarily */
- SHMInfo.shmaddr = ((void *) -1);
- SHMInfo.shmid = -1;
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
- /* Trying to create a 1x1 picture */
- GST_DEBUG ("XvShmCreateImage of 1x1");
- xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
- xcontext->im_format, NULL, 1, 1, &SHMInfo);
-
- /* Might cause an error, sync to ensure it is noticed */
- XSync (xcontext->disp, FALSE);
- if (!xvimage || error_caught) {
- GST_WARNING ("could not XvShmCreateImage a 1x1 image");
- goto beach;
- }
- size = xvimage->data_size;
-
- SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
- if (SHMInfo.shmid == -1) {
- GST_WARNING ("could not get shared memory of %d bytes", size);
- goto beach;
- }
-
- SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
- if (SHMInfo.shmaddr == ((void *) -1)) {
- GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
- /* Clean up the shared memory segment */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
- goto beach;
- }
-
- /* Delete the shared memory segment as soon as we manage to attach.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-
- xvimage->data = SHMInfo.shmaddr;
- SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
- GST_WARNING ("Failed to XShmAttach");
- goto beach;
- }
-
- /* Sync to ensure we see any errors we caused */
- XSync (xcontext->disp, FALSE);
-
- GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
- SHMInfo.shmseg);
-
- if (!error_caught) {
- did_attach = TRUE;
- /* store whether we succeeded in result */
- result = TRUE;
- }
-
-beach:
- /* Sync to ensure we swallow any errors we caused and reset error_caught */
- XSync (xcontext->disp, FALSE);
-
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- if (did_attach) {
- GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
- SHMInfo.shmid, SHMInfo.shmseg);
- XShmDetach (xcontext->disp, &SHMInfo);
- XSync (xcontext->disp, FALSE);
- }
- if (SHMInfo.shmaddr != ((void *) -1))
- shmdt (SHMInfo.shmaddr);
- if (xvimage)
- XFree (xvimage);
- return result;
-}
-#endif /* HAVE_XSHM */
-
-/* This function handles GstXvImage creation depending on XShm availability */
-static GstXvImageBuffer *
-gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
-{
- GstXvImageBuffer *xvimage = NULL;
- GstStructure *structure = NULL;
- gboolean succeeded = FALSE;
- int (*handler) (Display *, XErrorEvent *);
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
- GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer");
-
- structure = gst_caps_get_structure (caps, 0);
-
- if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
- !gst_structure_get_int (structure, "height", &xvimage->height)) {
- GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
- }
-
- GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
- xvimage->height);
-
- xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
- if (xvimage->im_format == -1) {
- GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
- GST_PTR_FORMAT, caps);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height), ("Invalid input caps"));
- goto beach_unlocked;
- }
- xvimage->xvimagesink = gst_object_ref (xvimagesink);
-
- g_mutex_lock (xvimagesink->x_lock);
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- int expected_size;
-
- xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- xvimage->im_format, NULL,
- xvimage->width, xvimage->height, &xvimage->SHMInfo);
- if (!xvimage->xvimage || error_caught) {
- g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height),
- ("could not XvShmCreateImage a %dx%d image",
- xvimage->width, xvimage->height));
- goto beach_unlocked;
- }
-
- /* we have to use the returned data_size for our shm size */
- xvimage->size = xvimage->xvimage->data_size;
- GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
- xvimage->size);
-
- /* calculate the expected size. This is only for sanity checking the
- * number we get from X. */
- switch (xvimage->im_format) {
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- expected_size =
- GST_ROUND_UP_2 (xvimage->height) * GST_ROUND_UP_4 (xvimage->width);
- expected_size +=
- GST_ROUND_UP_2 (xvimage->height) * GST_ROUND_UP_8 (xvimage->width) /
- 2;
- break;
- case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
- case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
- break;
- default:
- expected_size = 0;
- break;
- }
- if (expected_size != 0 && xvimage->size != expected_size) {
- GST_WARNING_OBJECT (xvimagesink,
- "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
- xvimage->size, expected_size);
- }
-
- /* Be verbose about our XvImage stride */
- {
- guint plane;
-
- for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
- GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
- "offset of %d", plane, xvimage->xvimage->pitches[plane],
- xvimage->xvimage->offsets[plane]);
- }
- }
-
- xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
- IPC_CREAT | 0777);
- if (xvimage->SHMInfo.shmid == -1) {
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height),
- ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
- xvimage->size));
- goto beach_unlocked;
- }
-
- xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
- if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height),
- ("Failed to shmat: %s", g_strerror (errno)));
- /* Clean up the shared memory segment */
- shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
- goto beach_unlocked;
- }
-
- /* Delete the shared memory segment as soon as we manage to attach.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
-
- xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
- xvimage->SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimage->width, xvimage->height), ("Failed to XShmAttach"));
- goto beach_unlocked;
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
- GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
- xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
- } else
-#endif /* HAVE_XSHM */
- {
- xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- xvimage->im_format, NULL, xvimage->width, xvimage->height);
- if (!xvimage->xvimage || error_caught) {
- g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create outputimage buffer of %dx%d pixels",
- xvimage->width, xvimage->height),
- ("could not XvCreateImage a %dx%d image",
- xvimage->width, xvimage->height));
- goto beach_unlocked;
- }
-
- /* we have to use the returned data_size for our image size */
- xvimage->size = xvimage->xvimage->data_size;
- xvimage->xvimage->data = g_malloc (xvimage->size);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
- }
-
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- succeeded = TRUE;
-
- GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
- GST_BUFFER_SIZE (xvimage) = xvimage->size;
-
- g_mutex_unlock (xvimagesink->x_lock);
-
-beach_unlocked:
- if (!succeeded) {
- gst_xvimage_buffer_free (xvimage);
- xvimage = NULL;
- }
-
- return xvimage;
-}
-
-/* We are called with the x_lock taken */
-static void
-gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
- GstXWindow * xwindow, GstVideoRectangle rect)
-{
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
- g_return_if_fail (xwindow != NULL);
-
- XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
- xvimagesink->xcontext->black);
-
- /* Left border */
- if (rect.x > 0) {
- XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, rect.x, xwindow->height);
- }
-
- /* Right border */
- if ((rect.x + rect.w) < xwindow->width) {
- XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
- rect.x + rect.w, 0, xwindow->width, xwindow->height);
- }
-
- /* Top border */
- if (rect.y > 0) {
- XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, xwindow->width, rect.y);
- }
-
- /* Bottom border */
- if ((rect.y + rect.h) < xwindow->height) {
- XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, rect.y + rect.h, xwindow->width, xwindow->height);
- }
-}
-
-/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
- * if no window was available */
-static gboolean
-gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
- GstXvImageBuffer * xvimage)
-{
- GstVideoRectangle src, dst, result;
- gboolean draw_border = FALSE;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
-
- /* We take the flow_lock. If expose is in there we don't want to run
- concurrently from the data flow thread */
- g_mutex_lock (xvimagesink->flow_lock);
-
- if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
- g_mutex_unlock (xvimagesink->flow_lock);
- return FALSE;
- }
-
- /* Draw borders when displaying the first frame. After this
- draw borders only on expose event or after a size change. */
- if (!xvimagesink->cur_image || xvimagesink->draw_border) {
- draw_border = TRUE;
- xvimagesink->draw_border = FALSE;
- }
-
- /* Store a reference to the last image we put, lose the previous one */
- if (xvimage && xvimagesink->cur_image != xvimage) {
- if (xvimagesink->cur_image) {
- GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
- gst_buffer_unref (xvimagesink->cur_image);
- }
- GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
- xvimagesink->cur_image =
- GST_XVIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER (xvimage)));
- }
-
- /* Expose sends a NULL image, we take the latest frame */
- if (!xvimage) {
- draw_border = TRUE;
- if (xvimagesink->cur_image) {
- xvimage = xvimagesink->cur_image;
- } else {
- g_mutex_unlock (xvimagesink->flow_lock);
- return TRUE;
- }
- }
-
- gst_xvimagesink_xwindow_update_geometry (xvimagesink, xvimagesink->xwindow);
-
- /* We use the calculated geometry from _setcaps as a source to respect
- source and screen pixel aspect ratios. */
- src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
- src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
- dst.w = xvimagesink->xwindow->width;
- dst.h = xvimagesink->xwindow->height;
-
- if (xvimagesink->keep_aspect) {
- gst_video_sink_center_rect (src, dst, &result, TRUE);
- } else {
- result.x = result.y = 0;
- result.w = dst.w;
- result.h = dst.h;
- }
-
- g_mutex_lock (xvimagesink->x_lock);
-
- if (draw_border) {
- gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow,
- result);
- }
-
- /* We scale to the window's geometry */
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- GST_LOG_OBJECT (xvimagesink,
- "XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
- GST_PTR_FORMAT,
- xvimage->width, xvimage->height,
- xvimagesink->xwindow->width, xvimagesink->xwindow->height, xvimage);
-
- XvShmPutImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- xvimagesink->xwindow->win,
- xvimagesink->xwindow->gc, xvimage->xvimage,
- 0, 0, xvimage->width, xvimage->height,
- result.x, result.y, result.w, result.h, FALSE);
- } else
-#endif /* HAVE_XSHM */
- {
- XvPutImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- xvimagesink->xwindow->win,
- xvimagesink->xwindow->gc, xvimage->xvimage,
- 0, 0, xvimage->width, xvimage->height,
- result.x, result.y, result.w, result.h);
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_mutex_unlock (xvimagesink->flow_lock);
-
- return TRUE;
-}
-
-static gboolean
-gst_xvimagesink_xwindow_decorate (GstXvImageSink * xvimagesink,
- GstXWindow * window)
-{
- Atom hints_atom = None;
- MotifWmHints *hints;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE);
- g_return_val_if_fail (window != NULL, FALSE);
-
- g_mutex_lock (xvimagesink->x_lock);
-
- hints_atom = XInternAtom (xvimagesink->xcontext->disp, "_MOTIF_WM_HINTS",
- True);
- if (hints_atom == None) {
- g_mutex_unlock (xvimagesink->x_lock);
- return FALSE;
- }
-
- hints = g_malloc0 (sizeof (MotifWmHints));
-
- hints->flags |= MWM_HINTS_DECORATIONS;
- hints->decorations = 1 << 0;
-
- XChangeProperty (xvimagesink->xcontext->disp, window->win,
- hints_atom, hints_atom, 32, PropModeReplace,
- (guchar *) hints, sizeof (MotifWmHints) / sizeof (long));
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_free (hints);
-
- return TRUE;
-}
-
-/* This function handles a GstXWindow creation
- * The width and height are the actual pixel size on the display */
-static GstXWindow *
-gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink,
- gint width, gint height)
-{
- GstXWindow *xwindow = NULL;
- XGCValues values;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- xwindow = g_new0 (GstXWindow, 1);
-
- xwindow->width = width;
- xwindow->height = height;
- xwindow->internal = TRUE;
-
- g_mutex_lock (xvimagesink->x_lock);
-
- xwindow->win = XCreateSimpleWindow (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->root,
- 0, 0, xwindow->width, xwindow->height,
- 0, 0, xvimagesink->xcontext->black);
-
- /* We have to do that to prevent X from redrawing the background on
- * ConfigureNotify. This takes away flickering of video when resizing. */
- XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None);
-
- if (xvimagesink->handle_events) {
- Atom wm_delete;
-
- XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
- StructureNotifyMask | PointerMotionMask | KeyPressMask |
- KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
-
- /* Tell the window manager we'd like delete client messages instead of
- * being killed */
- wm_delete = XInternAtom (xvimagesink->xcontext->disp,
- "WM_DELETE_WINDOW", True);
- if (wm_delete != None) {
- (void) XSetWMProtocols (xvimagesink->xcontext->disp, xwindow->win,
- &wm_delete, 1);
- }
- }
-
- xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
- xwindow->win, 0, &values);
-
- XMapRaised (xvimagesink->xcontext->disp, xwindow->win);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- gst_xvimagesink_xwindow_decorate (xvimagesink, xwindow);
-
- gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (xvimagesink), xwindow->win);
-
- return xwindow;
-}
-
-/* This function destroys a GstXWindow */
-static void
-gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink,
- GstXWindow * xwindow)
-{
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- g_mutex_lock (xvimagesink->x_lock);
-
- /* If we did not create that window we just free the GC and let it live */
- if (xwindow->internal)
- XDestroyWindow (xvimagesink->xcontext->disp, xwindow->win);
- else
- XSelectInput (xvimagesink->xcontext->disp, xwindow->win, 0);
-
- XFreeGC (xvimagesink->xcontext->disp, xwindow->gc);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_free (xwindow);
-}
-
-static void
-gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink,
- GstXWindow * xwindow)
-{
- XWindowAttributes attr;
-
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- /* Update the window geometry */
- g_mutex_lock (xvimagesink->x_lock);
-
- XGetWindowAttributes (xvimagesink->xcontext->disp,
- xvimagesink->xwindow->win, &attr);
-
- xvimagesink->xwindow->width = attr.width;
- xvimagesink->xwindow->height = attr.height;
-
- g_mutex_unlock (xvimagesink->x_lock);
-}
-
-static void
-gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink,
- GstXWindow * xwindow)
-{
- g_return_if_fail (xwindow != NULL);
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- g_mutex_lock (xvimagesink->x_lock);
-
- XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id,
- xwindow->win);
-
- XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
- xvimagesink->xcontext->black);
-
- XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
- 0, 0, xwindow->width, xwindow->height);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-}
-
-/* This function commits our internal colorbalance settings to our grabbed Xv
- port. If the xcontext is not initialized yet it simply returns */
-static void
-gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink)
-{
- GList *channels = NULL;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- /* If we haven't initialized the X context we can't update anything */
- if (xvimagesink->xcontext == NULL)
- return;
-
- /* For each channel of the colorbalance we calculate the correct value
- doing range conversion and then set the Xv port attribute to match our
- values. */
- channels = xvimagesink->xcontext->channels_list;
-
- while (channels) {
- if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
- GstColorBalanceChannel *channel = NULL;
- Atom prop_atom;
- gint value = 0;
- gdouble convert_coef;
-
- channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
- g_object_ref (channel);
-
- /* Our range conversion coef */
- convert_coef = (channel->max_value - channel->min_value) / 2000.0;
-
- if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
- value = (xvimagesink->hue + 1000) * convert_coef + channel->min_value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
- value = (xvimagesink->saturation + 1000) * convert_coef +
- channel->min_value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
- value = (xvimagesink->contrast + 1000) * convert_coef +
- channel->min_value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
- value = (xvimagesink->brightness + 1000) * convert_coef +
- channel->min_value;
- } else {
- g_warning ("got an unknown channel %s", channel->label);
- g_object_unref (channel);
- return;
- }
-
- /* Committing to Xv port */
- g_mutex_lock (xvimagesink->x_lock);
- prop_atom =
- XInternAtom (xvimagesink->xcontext->disp, channel->label, True);
- if (prop_atom != None) {
- XvSetPortAttribute (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id, prop_atom, value);
- }
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_object_unref (channel);
- }
- channels = g_list_next (channels);
- }
-}
-
-/* This function handles XEvents that might be in the queue. It generates
- GstEvent that will be sent upstream in the pipeline to handle interactivity
- and navigation. It will also listen for configure events on the window to
- trigger caps renegotiation so on the fly software scaling can work. */
-static void
-gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
-{
- XEvent e;
- guint pointer_x = 0, pointer_y = 0;
- gboolean pointer_moved = FALSE;
- gboolean exposed = FALSE, configured = FALSE;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- /* We get all pointer motion events, only the last position is
- interesting. */
- g_mutex_lock (xvimagesink->flow_lock);
- g_mutex_lock (xvimagesink->x_lock);
- while (XCheckWindowEvent (xvimagesink->xcontext->disp,
- xvimagesink->xwindow->win, PointerMotionMask, &e)) {
- g_mutex_unlock (xvimagesink->x_lock);
- g_mutex_unlock (xvimagesink->flow_lock);
-
- switch (e.type) {
- case MotionNotify:
- pointer_x = e.xmotion.x;
- pointer_y = e.xmotion.y;
- pointer_moved = TRUE;
- break;
- default:
- break;
- }
- g_mutex_lock (xvimagesink->flow_lock);
- g_mutex_lock (xvimagesink->x_lock);
- }
- if (pointer_moved) {
- g_mutex_unlock (xvimagesink->x_lock);
- g_mutex_unlock (xvimagesink->flow_lock);
-
- GST_DEBUG ("xvimagesink pointer moved over window at %d,%d",
- pointer_x, pointer_y);
- gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
- "mouse-move", 0, e.xbutton.x, e.xbutton.y);
-
- g_mutex_lock (xvimagesink->flow_lock);
- g_mutex_lock (xvimagesink->x_lock);
- }
-
- /* We get all events on our window to throw them upstream */
- while (XCheckWindowEvent (xvimagesink->xcontext->disp,
- xvimagesink->xwindow->win,
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
- &e)) {
- KeySym keysym;
-
- /* We lock only for the X function call */
- g_mutex_unlock (xvimagesink->x_lock);
- g_mutex_unlock (xvimagesink->flow_lock);
-
- switch (e.type) {
- case ButtonPress:
- /* Mouse button pressed over our window. We send upstream
- events for interactivity/navigation */
- GST_DEBUG ("xvimagesink button %d pressed over window at %d,%d",
- e.xbutton.button, e.xbutton.x, e.xbutton.y);
- gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
- "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y);
- break;
- case ButtonRelease:
- /* Mouse button released over our window. We send upstream
- events for interactivity/navigation */
- GST_DEBUG ("xvimagesink button %d released over window at %d,%d",
- e.xbutton.button, e.xbutton.x, e.xbutton.y);
- gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink),
- "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y);
- break;
- case KeyPress:
- case KeyRelease:
- /* Key pressed/released over our window. We send upstream
- events for interactivity/navigation */
- GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d",
- e.xkey.keycode, e.xkey.x, e.xkey.y);
- g_mutex_lock (xvimagesink->x_lock);
- keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp,
- e.xkey.keycode, 0);
- g_mutex_unlock (xvimagesink->x_lock);
- if (keysym != NoSymbol) {
- char *key_str = NULL;
-
- g_mutex_lock (xvimagesink->x_lock);
- key_str = XKeysymToString (keysym);
- g_mutex_unlock (xvimagesink->x_lock);
- gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
- e.type == KeyPress ? "key-press" : "key-release", key_str);
- } else {
- gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink),
- e.type == KeyPress ? "key-press" : "key-release", "unknown");
- }
- break;
- default:
- GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type);
- }
- g_mutex_lock (xvimagesink->flow_lock);
- g_mutex_lock (xvimagesink->x_lock);
- }
-
- /* Handle Expose */
- while (XCheckWindowEvent (xvimagesink->xcontext->disp,
- xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
- switch (e.type) {
- case Expose:
- exposed = TRUE;
- break;
- case ConfigureNotify:
- configured = TRUE;
- break;
- default:
- break;
- }
- }
-
- if (xvimagesink->handle_expose && (exposed || configured)) {
- g_mutex_unlock (xvimagesink->x_lock);
- g_mutex_unlock (xvimagesink->flow_lock);
-
- gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
-
- g_mutex_lock (xvimagesink->flow_lock);
- g_mutex_lock (xvimagesink->x_lock);
- }
-
- /* Handle Display events */
- while (XPending (xvimagesink->xcontext->disp)) {
- XNextEvent (xvimagesink->xcontext->disp, &e);
-
- switch (e.type) {
- case ClientMessage:{
- Atom wm_delete;
-
- wm_delete = XInternAtom (xvimagesink->xcontext->disp,
- "WM_DELETE_WINDOW", True);
- if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) {
- /* Handle window deletion by posting an error on the bus */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND,
- ("Output window was closed"), (NULL));
-
- g_mutex_unlock (xvimagesink->x_lock);
- gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
- xvimagesink->xwindow = NULL;
- g_mutex_lock (xvimagesink->x_lock);
- }
- break;
- }
- default:
- break;
- }
- }
-
- g_mutex_unlock (xvimagesink->x_lock);
- g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_lookup_xv_port_from_adaptor (GstXContext * xcontext,
- XvAdaptorInfo * adaptors, int adaptor_no)
-{
- gint j;
-
- /* Do we support XvImageMask ? */
- if (!(adaptors[adaptor_no].type & XvImageMask))
- return;
-
- /* We found such an adaptor, looking for an available port */
- for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
- /* We try to grab the port */
- if (Success == XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j,
- 0)) {
- xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
- GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name,
- adaptors[adaptor_no].num_ports);
- }
- }
-}
-
-/* This function generates a caps with all supported format by the first
- Xv grabable port we find. We store each one of the supported formats in a
- format list and append the format to a newly created caps that we return
- If this function does not return NULL because of an error, it also grabs
- the port via XvGrabPort */
-static GstCaps *
-gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
- GstXContext * xcontext)
-{
- gint i;
- XvAdaptorInfo *adaptors;
- gint nb_formats;
- XvImageFormatValues *formats = NULL;
- guint nb_encodings;
- XvEncodingInfo *encodings = NULL;
- gulong max_w = G_MAXINT, max_h = G_MAXINT;
- GstCaps *caps = NULL;
- GstCaps *rgb_caps = NULL;
-
- g_return_val_if_fail (xcontext != NULL, NULL);
-
- /* First let's check that XVideo extension is available */
- if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
- ("Could not initialise Xv output"),
- ("XVideo extension is not available"));
- return NULL;
- }
-
- /* Then we get adaptors list */
- if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
- &xcontext->nb_adaptors, &adaptors)) {
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
- ("Could not initialise Xv output"),
- ("Failed getting XV adaptors list"));
- return NULL;
- }
-
- xcontext->xv_port_id = 0;
-
- GST_DEBUG ("Found %u XV adaptor(s)", xcontext->nb_adaptors);
-
- xcontext->adaptors =
- (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
-
- /* Now fill up our adaptor name array */
- for (i = 0; i < xcontext->nb_adaptors; i++) {
- xcontext->adaptors[i] = g_strdup (adaptors[i].name);
- }
-
- if (xvimagesink->adaptor_no >= 0 &&
- xvimagesink->adaptor_no < xcontext->nb_adaptors) {
- /* Find xv port from user defined adaptor */
- gst_lookup_xv_port_from_adaptor (xcontext, adaptors,
- xvimagesink->adaptor_no);
- }
-
- if (!xcontext->xv_port_id) {
- /* Now search for an adaptor that supports XvImageMask */
- for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
- gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
- xvimagesink->adaptor_no = i;
- }
- }
-
- XvFreeAdaptorInfo (adaptors);
-
- if (!xcontext->xv_port_id) {
- xvimagesink->adaptor_no = -1;
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, BUSY,
- ("Could not initialise Xv output"), ("No port available"));
- return NULL;
- }
-
- /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
- {
- int count;
- XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
- xcontext->xv_port_id, &count);
- static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
- static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
- static const char colorkey[] = "XV_COLORKEY";
-
- for (i = 0; i < count; i++)
- if (!strcmp (attr[i].name, autopaint)) {
- const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
-
- XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, 1);
- break;
- }
-
- for (i = 0; i < count; i++)
- if (!strcmp (attr[i].name, dbl_buffer)) {
- const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
-
- XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
- (xvimagesink->double_buffer ? 1 : 0));
- break;
- }
-
- /* Set the colorkey to something that is dark but hopefully won't randomly
- * appear on the screen elsewhere (ie not black or greys) */
- for (i = 0; i < count; i++)
- if (!strcmp (attr[i].name, colorkey)) {
- const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
- guint32 ckey;
- guint32 keymask;
- gint bits;
- gboolean set_attr = TRUE;
-
- /* Count the bits in the colorkey mask 'max' value */
- bits = 0;
- for (keymask = (guint32) (attr[i].max_value);
- keymask != 0; keymask >>= 1)
- bits++;
-
- /* set a colorkey in the right format RGB565/RGB888
- * note that the colorkey is independent from the display
- * depth (xcontext->depth). We only handle these 2 cases, because
- * they're the only types of devices we've encountered. If we don't
- * recognise it, leave it alone */
- if (bits == 16)
- ckey = (1 << 10) | (2 << 5) | 3;
- else if (bits == 24 || bits == 32)
- ckey = (1 << 16) | (2 << 8) | 3;
- else
- set_attr = FALSE;
-
-
- if (set_attr) {
- ckey = CLAMP (ckey, (guint32) attr[i].min_value,
- (guint32) attr[i].max_value);
- GST_LOG_OBJECT (xvimagesink,
- "Setting color key for display depth %d to 0x%x",
- xcontext->depth, ckey);
-
- XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
- (gint) ckey);
- } else {
- GST_LOG_OBJECT (xvimagesink,
- "Unknown bit depth for Xv Colorkey - not adjusting ");
- }
- break;
- }
-
- XFree (attr);
- }
-
- /* Get the list of encodings supported by the adapter and look for the
- * XV_IMAGE encoding so we can determine the maximum width and height
- * supported */
- XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
- &encodings);
-
- for (i = 0; i < nb_encodings; i++) {
- GST_LOG_OBJECT (xvimagesink,
- "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
- i, encodings[i].name, encodings[i].width, encodings[i].height,
- encodings[i].rate.numerator, encodings[i].rate.denominator);
- if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
- max_w = encodings[i].width;
- max_h = encodings[i].height;
- }
- }
-
- XvFreeEncodingInfo (encodings);
-
- /* We get all image formats supported by our port */
- formats = XvListImageFormats (xcontext->disp,
- xcontext->xv_port_id, &nb_formats);
- caps = gst_caps_new_empty ();
- for (i = 0; i < nb_formats; i++) {
- GstCaps *format_caps = NULL;
- gboolean is_rgb_format = FALSE;
-
- /* We set the image format of the xcontext to an existing one. This
- is just some valid image format for making our xshm calls check before
- caps negotiation really happens. */
- xcontext->im_format = formats[i].id;
-
- switch (formats[i].type) {
- case XvRGB:
- {
- XvImageFormatValues *fmt = &(formats[i]);
- gint endianness = G_BIG_ENDIAN;
-
- if (fmt->byte_order == LSBFirst) {
- /* our caps system handles 24/32bpp RGB as big-endian. */
- if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
- fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
- fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
- fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
-
- if (fmt->bits_per_pixel == 24) {
- fmt->red_mask >>= 8;
- fmt->green_mask >>= 8;
- fmt->blue_mask >>= 8;
- }
- } else
- endianness = G_LITTLE_ENDIAN;
- }
-
- format_caps = gst_caps_new_simple ("video/x-raw-rgb",
- "endianness", G_TYPE_INT, endianness,
- "depth", G_TYPE_INT, fmt->depth,
- "bpp", G_TYPE_INT, fmt->bits_per_pixel,
- "red_mask", G_TYPE_INT, fmt->red_mask,
- "green_mask", G_TYPE_INT, fmt->green_mask,
- "blue_mask", G_TYPE_INT, fmt->blue_mask,
- "width", GST_TYPE_INT_RANGE, 1, max_w,
- "height", GST_TYPE_INT_RANGE, 1, max_h,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
-
- is_rgb_format = TRUE;
- break;
- }
- case XvYUV:
- format_caps = gst_caps_new_simple ("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, formats[i].id,
- "width", GST_TYPE_INT_RANGE, 1, max_w,
- "height", GST_TYPE_INT_RANGE, 1, max_h,
- "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (format_caps) {
- GstXvImageFormat *format = NULL;
-
- format = g_new0 (GstXvImageFormat, 1);
- if (format) {
- format->format = formats[i].id;
- format->caps = gst_caps_copy (format_caps);
- xcontext->formats_list = g_list_append (xcontext->formats_list, format);
- }
-
- if (is_rgb_format) {
- if (rgb_caps == NULL)
- rgb_caps = format_caps;
- else
- gst_caps_append (rgb_caps, format_caps);
- } else
- gst_caps_append (caps, format_caps);
- }
- }
-
- /* Collected all caps into either the caps or rgb_caps structures.
- * Append rgb_caps on the end of YUV, so that YUV is always preferred */
- if (rgb_caps)
- gst_caps_append (caps, rgb_caps);
-
- if (formats)
- XFree (formats);
-
- GST_DEBUG ("Generated the following caps: %" GST_PTR_FORMAT, caps);
-
- if (gst_caps_is_empty (caps)) {
- gst_caps_unref (caps);
- XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
- GST_ELEMENT_ERROR (xvimagesink, STREAM, WRONG_TYPE, (NULL),
- ("No supported format found"));
- return NULL;
- }
-
- return caps;
-}
-
-static gpointer
-gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink)
-{
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- GST_OBJECT_LOCK (xvimagesink);
- while (xvimagesink->running) {
- GST_OBJECT_UNLOCK (xvimagesink);
-
- if (xvimagesink->xwindow) {
- gst_xvimagesink_handle_xevents (xvimagesink);
- }
- g_usleep (50000);
-
- GST_OBJECT_LOCK (xvimagesink);
- }
- GST_OBJECT_UNLOCK (xvimagesink);
-
- return NULL;
-}
-
-/* This function calculates the pixel aspect ratio based on the properties
- * in the xcontext structure and stores it there. */
-static void
-gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
-{
- static const gint par[][2] = {
- {1, 1}, /* regular screen */
- {16, 15}, /* PAL TV */
- {11, 10}, /* 525 line Rec.601 video */
- {54, 59}, /* 625 line Rec.601 video */
- {64, 45}, /* 1280x1024 on 16:9 display */
- {5, 3}, /* 1280x1024 on 4:3 display */
- {4, 3} /* 800x600 on 16:9 display */
- };
- gint i;
- gint index;
- gdouble ratio;
- gdouble delta;
-
-#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
-
- /* first calculate the "real" ratio based on the X values;
- * which is the "physical" w/h divided by the w/h in pixels of the display */
- ratio = (gdouble) (xcontext->widthmm * xcontext->height)
- / (xcontext->heightmm * xcontext->width);
-
- /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
- * override here */
- if (xcontext->width == 720 && xcontext->height == 576) {
- ratio = 4.0 * 576 / (3.0 * 720);
- }
- GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
- /* now find the one from par[][2] with the lowest delta to the real one */
- delta = DELTA (0);
- index = 0;
-
- for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
- gdouble this_delta = DELTA (i);
-
- if (this_delta < delta) {
- index = i;
- delta = this_delta;
- }
- }
-
- GST_DEBUG ("Decided on index %d (%d/%d)", index,
- par[index][0], par[index][1]);
-
- g_free (xcontext->par);
- xcontext->par = g_new0 (GValue, 1);
- g_value_init (xcontext->par, GST_TYPE_FRACTION);
- gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
- GST_DEBUG ("set xcontext PAR to %d/%d",
- gst_value_get_fraction_numerator (xcontext->par),
- gst_value_get_fraction_denominator (xcontext->par));
-}
-
-/* This function gets the X Display and global info about it. Everything is
- stored in our object and will be cleaned when the object is disposed. Note
- here that caps for supported format are generated without any window or
- image creation */
-static GstXContext *
-gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
-{
- GstXContext *xcontext = NULL;
- XPixmapFormatValues *px_formats = NULL;
- gint nb_formats = 0, i, j, N_attr;
- XvAttribute *xv_attr;
- Atom prop_atom;
- char *channels[4] = { "XV_HUE", "XV_SATURATION",
- "XV_BRIGHTNESS", "XV_CONTRAST"
- };
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- xcontext = g_new0 (GstXContext, 1);
- xcontext->im_format = 0;
-
- g_mutex_lock (xvimagesink->x_lock);
-
- xcontext->disp = XOpenDisplay (xvimagesink->display_name);
-
- if (!xcontext->disp) {
- g_mutex_unlock (xvimagesink->x_lock);
- g_free (xcontext);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Could not initialise Xv output"), ("Could not open display"));
- return NULL;
- }
-
- xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
- xcontext->screen_num = DefaultScreen (xcontext->disp);
- xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
- xcontext->root = DefaultRootWindow (xcontext->disp);
- xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
- xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
- xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
-
- xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
- xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
- xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
- xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
-
- GST_DEBUG_OBJECT (xvimagesink, "X reports %dx%d pixels and %d mm x %d mm",
- xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
-
- gst_xvimagesink_calculate_pixel_aspect_ratio (xcontext);
- /* We get supported pixmap formats at supported depth */
- px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
-
- if (!px_formats) {
- XCloseDisplay (xcontext->disp);
- g_mutex_unlock (xvimagesink->x_lock);
- g_free (xcontext->par);
- g_free (xcontext);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS,
- ("Could not initialise Xv output"), ("Could not get pixel formats"));
- return NULL;
- }
-
- /* We get bpp value corresponding to our running depth */
- for (i = 0; i < nb_formats; i++) {
- if (px_formats[i].depth == xcontext->depth)
- xcontext->bpp = px_formats[i].bits_per_pixel;
- }
-
- XFree (px_formats);
-
- xcontext->endianness =
- (ImageByteOrder (xcontext->disp) ==
- LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
-
- /* our caps system handles 24/32bpp RGB as big-endian. */
- if ((xcontext->bpp == 24 || xcontext->bpp == 32) &&
- xcontext->endianness == G_LITTLE_ENDIAN) {
- xcontext->endianness = G_BIG_ENDIAN;
- xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
- xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
- xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
- if (xcontext->bpp == 24) {
- xcontext->visual->red_mask >>= 8;
- xcontext->visual->green_mask >>= 8;
- xcontext->visual->blue_mask >>= 8;
- }
- }
-
- xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext);
-
- if (!xcontext->caps) {
- XCloseDisplay (xcontext->disp);
- g_mutex_unlock (xvimagesink->x_lock);
- g_free (xcontext->par);
- g_free (xcontext);
- /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
- return NULL;
- }
-#ifdef HAVE_XSHM
- /* Search for XShm extension support */
- if (XShmQueryExtension (xcontext->disp) &&
- gst_xvimagesink_check_xshm_calls (xcontext)) {
- xcontext->use_xshm = TRUE;
- GST_DEBUG ("xvimagesink is using XShm extension");
- } else
-#endif /* HAVE_XSHM */
- {
- xcontext->use_xshm = FALSE;
- GST_DEBUG ("xvimagesink is not using XShm extension");
- }
-
- xv_attr = XvQueryPortAttributes (xcontext->disp,
- xcontext->xv_port_id, &N_attr);
-
-
- /* Generate the channels list */
- for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
- XvAttribute *matching_attr = NULL;
-
- /* Retrieve the property atom if it exists. If it doesn't exist,
- * the attribute itself must not either, so we can skip */
- prop_atom = XInternAtom (xcontext->disp, channels[i], True);
- if (prop_atom == None)
- continue;
-
- if (xv_attr != NULL) {
- for (j = 0; j < N_attr && matching_attr == NULL; ++j)
- if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name))
- matching_attr = xv_attr + j;
- }
-
- if (matching_attr) {
- GstColorBalanceChannel *channel;
-
- channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
- channel->label = g_strdup (channels[i]);
- channel->min_value = matching_attr ? matching_attr->min_value : -1000;
- channel->max_value = matching_attr ? matching_attr->max_value : 1000;
-
- xcontext->channels_list = g_list_append (xcontext->channels_list,
- channel);
-
- /* If the colorbalance settings have not been touched we get Xv values
- as defaults and update our internal variables */
- if (!xvimagesink->cb_changed) {
- gint val;
-
- XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id,
- prop_atom, &val);
- /* Normalize val to [-1000, 1000] */
- val = -1000 + 2000 * (val - channel->min_value) /
- (channel->max_value - channel->min_value);
-
- if (!g_ascii_strcasecmp (channels[i], "XV_HUE"))
- xvimagesink->hue = val;
- else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION"))
- xvimagesink->saturation = val;
- else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS"))
- xvimagesink->brightness = val;
- else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST"))
- xvimagesink->contrast = val;
- }
- }
- }
-
- if (xv_attr)
- XFree (xv_attr);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- /* Setup our event listening thread */
- GST_OBJECT_LOCK (xvimagesink);
- xvimagesink->running = TRUE;
- xvimagesink->event_thread = g_thread_create (
- (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
- GST_OBJECT_UNLOCK (xvimagesink);
-
- return xcontext;
-}
-
-/* This function cleans the X context. Closing the Display, releasing the XV
- port and unrefing the caps for supported formats. */
-static void
-gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
-{
- GList *formats_list, *channels_list;
- GstXContext *xcontext;
- gint i = 0;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- GST_OBJECT_LOCK (xvimagesink);
- if (xvimagesink->xcontext == NULL) {
- GST_OBJECT_UNLOCK (xvimagesink);
- return;
- }
-
- /* Take the XContext from the sink and clean it up */
- xcontext = xvimagesink->xcontext;
- xvimagesink->xcontext = NULL;
-
- GST_OBJECT_UNLOCK (xvimagesink);
-
-
- formats_list = xcontext->formats_list;
-
- while (formats_list) {
- GstXvImageFormat *format = formats_list->data;
-
- gst_caps_unref (format->caps);
- g_free (format);
- formats_list = g_list_next (formats_list);
- }
-
- if (xcontext->formats_list)
- g_list_free (xcontext->formats_list);
-
- channels_list = xcontext->channels_list;
-
- while (channels_list) {
- GstColorBalanceChannel *channel = channels_list->data;
-
- g_object_unref (channel);
- channels_list = g_list_next (channels_list);
- }
-
- if (xcontext->channels_list)
- g_list_free (xcontext->channels_list);
-
- gst_caps_unref (xcontext->caps);
- if (xcontext->last_caps)
- gst_caps_replace (&xcontext->last_caps, NULL);
-
- for (i = 0; i < xcontext->nb_adaptors; i++) {
- g_free (xcontext->adaptors[i]);
- }
-
- g_free (xcontext->adaptors);
-
- g_free (xcontext->par);
-
- g_mutex_lock (xvimagesink->x_lock);
-
- GST_DEBUG_OBJECT (xvimagesink, "Closing display and freeing X Context");
-
- XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
-
- XCloseDisplay (xcontext->disp);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_free (xcontext);
-}
-
-static void
-gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
-{
- g_mutex_lock (xvimagesink->pool_lock);
-
- while (xvimagesink->image_pool) {
- GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
-
- xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
- xvimagesink->image_pool);
- gst_xvimage_buffer_free (xvimage);
- }
-
- g_mutex_unlock (xvimagesink->pool_lock);
-}
-
-/* Element stuff */
-
-/* This function tries to get a format matching with a given caps in the
- supported list of formats we generated in gst_xvimagesink_get_xv_support */
-static gint
-gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
- GstCaps * caps)
-{
- GList *list = NULL;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
-
- list = xvimagesink->xcontext->formats_list;
-
- while (list) {
- GstXvImageFormat *format = list->data;
-
- if (format) {
- GstCaps *icaps = NULL;
-
- icaps = gst_caps_intersect (caps, format->caps);
- if (!gst_caps_is_empty (icaps)) {
- gst_caps_unref (icaps);
- return format->format;
- }
- gst_caps_unref (icaps);
- }
- list = g_list_next (list);
- }
-
- return -1;
-}
-
-static GstCaps *
-gst_xvimagesink_getcaps (GstBaseSink * bsink)
-{
- GstXvImageSink *xvimagesink;
-
- xvimagesink = GST_XVIMAGESINK (bsink);
-
- if (xvimagesink->xcontext)
- return gst_caps_ref (xvimagesink->xcontext->caps);
-
- return
- gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
- (xvimagesink)));
-}
-
-static gboolean
-gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
-{
- GstXvImageSink *xvimagesink;
- GstStructure *structure;
- GstCaps *intersection;
- guint32 im_format = 0;
- gboolean ret;
- gint video_width, video_height;
- gint video_par_n, video_par_d; /* video's PAR */
- gint display_par_n, display_par_d; /* display's PAR */
- const GValue *caps_par;
- const GValue *fps;
- guint num, den;
-
- xvimagesink = GST_XVIMAGESINK (bsink);
-
- GST_DEBUG_OBJECT (xvimagesink,
- "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %"
- GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps);
-
- intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps);
- GST_DEBUG_OBJECT (xvimagesink, "intersection returned %" GST_PTR_FORMAT,
- intersection);
- if (gst_caps_is_empty (intersection)) {
- gst_caps_unref (intersection);
- return FALSE;
- }
-
- gst_caps_unref (intersection);
-
- structure = gst_caps_get_structure (caps, 0);
- ret = gst_structure_get_int (structure, "width", &video_width);
- ret &= gst_structure_get_int (structure, "height", &video_height);
- fps = gst_structure_get_value (structure, "framerate");
- ret &= (fps != NULL);
-
- if (!ret) {
- GST_DEBUG_OBJECT (xvimagesink, "Failed to retrieve either width, "
- "height or framerate from intersected caps");
- return FALSE;
- }
-
- xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
- xvimagesink->fps_d = gst_value_get_fraction_denominator (fps);
-
- xvimagesink->video_width = video_width;
- xvimagesink->video_height = video_height;
- im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
- if (im_format == -1) {
- GST_DEBUG_OBJECT (xvimagesink,
- "Could not locate image format from caps %" GST_PTR_FORMAT, caps);
- return FALSE;
- }
-
- /* get aspect ratio from caps if it's present, and
- * convert video width and height to a display width and height
- * using wd / hd = wv / hv * PARv / PARd */
-
- /* get video's PAR */
- caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
- if (caps_par) {
- video_par_n = gst_value_get_fraction_numerator (caps_par);
- video_par_d = gst_value_get_fraction_denominator (caps_par);
- } else {
- video_par_n = 1;
- video_par_d = 1;
- }
- /* get display's PAR */
- if (xvimagesink->par) {
- display_par_n = gst_value_get_fraction_numerator (xvimagesink->par);
- display_par_d = gst_value_get_fraction_denominator (xvimagesink->par);
- } else {
- display_par_n = 1;
- display_par_d = 1;
- }
-
- if (!gst_video_calculate_display_ratio (&num, &den, video_width,
- video_height, video_par_n, video_par_d, display_par_n,
- display_par_d)) {
- GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
- ("Error calculating the output display ratio of the video."));
- return FALSE;
- }
-
- GST_DEBUG_OBJECT (xvimagesink,
- "video width/height: %dx%d, calculated display ratio: %d/%d",
- video_width, video_height, num, den);
-
- /* now find a width x height that respects this display ratio.
- * prefer those that have one of w/h the same as the incoming video
- * using wd / hd = num / den */
-
- /* start with same height, because of interlaced video */
- /* check hd / den is an integer scale factor, and scale wd with the PAR */
- if (video_height % den == 0) {
- GST_DEBUG_OBJECT (xvimagesink, "keeping video height");
- GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
- gst_util_uint64_scale_int (video_height, num, den);
- GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
- } else if (video_width % num == 0) {
- GST_DEBUG_OBJECT (xvimagesink, "keeping video width");
- GST_VIDEO_SINK_WIDTH (xvimagesink) = video_width;
- GST_VIDEO_SINK_HEIGHT (xvimagesink) = (guint)
- gst_util_uint64_scale_int (video_width, den, num);
- } else {
- GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height");
- GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint)
- gst_util_uint64_scale_int (video_height, num, den);
- GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height;
- }
- GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d",
- GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink));
-
- /* Notify application to set xwindow id now */
- g_mutex_lock (xvimagesink->flow_lock);
- if (!xvimagesink->xwindow) {
- g_mutex_unlock (xvimagesink->flow_lock);
- gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink));
- } else {
- g_mutex_unlock (xvimagesink->flow_lock);
- }
-
- /* Creating our window and our image with the display size in pixels */
- if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 ||
- GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0) {
- GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
- ("Error calculating the output display ratio of the video."));
- return FALSE;
- }
-
- g_mutex_lock (xvimagesink->flow_lock);
- if (!xvimagesink->xwindow) {
- xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
- GST_VIDEO_SINK_WIDTH (xvimagesink),
- GST_VIDEO_SINK_HEIGHT (xvimagesink));
- }
-
- /* After a resize, we want to redraw the borders in case the new frame size
- * doesn't cover the same area */
- xvimagesink->draw_border = TRUE;
-
- /* We renew our xvimage only if size or format changed;
- * the xvimage is the same size as the video pixel size */
- if ((xvimagesink->xvimage) &&
- ((im_format != xvimagesink->xvimage->im_format) ||
- (video_width != xvimagesink->xvimage->width) ||
- (video_height != xvimagesink->xvimage->height))) {
- GST_DEBUG_OBJECT (xvimagesink,
- "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
- GST_FOURCC_ARGS (im_format));
- GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
- gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
- xvimagesink->xvimage = NULL;
- }
-
- g_mutex_unlock (xvimagesink->flow_lock);
-
- return TRUE;
-}
-
-static GstStateChangeReturn
-gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstXvImageSink *xvimagesink;
- GstXContext *xcontext = NULL;
-
- xvimagesink = GST_XVIMAGESINK (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- /* Initializing the XContext */
- if (xvimagesink->xcontext == NULL) {
- xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
- if (xcontext == NULL)
- return GST_STATE_CHANGE_FAILURE;
- GST_OBJECT_LOCK (xvimagesink);
- if (xcontext)
- xvimagesink->xcontext = xcontext;
- GST_OBJECT_UNLOCK (xvimagesink);
- }
-
- /* update object's par with calculated one if not set yet */
- if (!xvimagesink->par) {
- xvimagesink->par = g_new0 (GValue, 1);
- gst_value_init_and_copy (xvimagesink->par, xvimagesink->xcontext->par);
- GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR");
- }
- /* call XSynchronize with the current value of synchronous */
- GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
- xvimagesink->synchronous ? "TRUE" : "FALSE");
- XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
- gst_xvimagesink_update_colorbalance (xvimagesink);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- g_mutex_lock (xvimagesink->flow_lock);
- if (xvimagesink->xwindow)
- gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
- g_mutex_unlock (xvimagesink->flow_lock);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- xvimagesink->fps_n = 0;
- xvimagesink->fps_d = 1;
- GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
- GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_xvimagesink_reset (xvimagesink);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-static void
-gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
- GstClockTime * start, GstClockTime * end)
-{
- GstXvImageSink *xvimagesink;
-
- xvimagesink = GST_XVIMAGESINK (bsink);
-
- if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
- *start = GST_BUFFER_TIMESTAMP (buf);
- if (GST_BUFFER_DURATION_IS_VALID (buf)) {
- *end = *start + GST_BUFFER_DURATION (buf);
- } else {
- if (xvimagesink->fps_n > 0) {
- *end = *start +
- gst_util_uint64_scale_int (GST_SECOND, xvimagesink->fps_d,
- xvimagesink->fps_n);
- }
- }
- }
-}
-
-static GstFlowReturn
-gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
-{
- GstXvImageSink *xvimagesink;
-
- xvimagesink = GST_XVIMAGESINK (bsink);
-
- /* If this buffer has been allocated using our buffer management we simply
- put the ximage which is in the PRIVATE pointer */
- if (GST_IS_XVIMAGE_BUFFER (buf)) {
- GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer");
- if (!gst_xvimagesink_xvimage_put (xvimagesink, GST_XVIMAGE_BUFFER (buf)))
- goto no_window;
- } else {
- GST_LOG_OBJECT (xvimagesink, "slow copy into bufferpool buffer");
- /* Else we have to copy the data into our private image, */
- /* if we have one... */
- if (!xvimagesink->xvimage) {
- GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
-
- xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
- GST_BUFFER_CAPS (buf));
-
- if (!xvimagesink->xvimage)
- /* The create method should have posted an informative error */
- goto no_image;
-
- if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- xvimagesink->xvimage->width, xvimagesink->xvimage->height),
- ("XServer allocated buffer size did not match input buffer"));
-
- gst_xvimage_buffer_destroy (xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- goto no_image;
- }
- }
-
- memcpy (xvimagesink->xvimage->xvimage->data,
- GST_BUFFER_DATA (buf),
- MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
-
- if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
- goto no_window;
- }
-
- return GST_FLOW_OK;
-
- /* ERRORS */
-no_image:
- {
- /* No image available. That's very bad ! */
- GST_WARNING_OBJECT (xvimagesink, "could not create image");
- return GST_FLOW_ERROR;
- }
-no_window:
- {
- /* No Window available to put our image into */
- GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
- return GST_FLOW_ERROR;
- }
-}
-
-/* Buffer management */
-
-static GstFlowReturn
-gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
- GstCaps * caps, GstBuffer ** buf)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstXvImageSink *xvimagesink;
- GstXvImageBuffer *xvimage = NULL;
- GstCaps *intersection = NULL;
- GstStructure *structure = NULL;
- gint width, height, image_format;
-
- xvimagesink = GST_XVIMAGESINK (bsink);
-
- if (G_LIKELY (xvimagesink->xcontext->last_caps &&
- gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
- GST_DEBUG_OBJECT (xvimagesink,
- "buffer alloc for same last_caps, reusing caps");
- intersection = gst_caps_ref (caps);
- image_format = xvimagesink->xcontext->last_format;
-
- goto reuse_last_caps;
- }
-
- GST_DEBUG_OBJECT (xvimagesink, "buffer alloc requested with caps %"
- GST_PTR_FORMAT ", intersecting with our caps %" GST_PTR_FORMAT, caps,
- xvimagesink->xcontext->caps);
-
- /* Check the caps against our xcontext */
- intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps);
-
- /* Ensure the returned caps are fixed */
- gst_caps_truncate (intersection);
-
- GST_DEBUG_OBJECT (xvimagesink, "intersection in buffer alloc returned %"
- GST_PTR_FORMAT, intersection);
-
- if (gst_caps_is_empty (intersection)) {
- /* So we don't support this kind of buffer, let's define one we'd like */
- GstCaps *new_caps = gst_caps_copy (caps);
-
- structure = gst_caps_get_structure (new_caps, 0);
-
- /* Try with YUV first */
- gst_structure_set_name (structure, "video/x-raw-yuv");
- gst_structure_remove_field (structure, "format");
- gst_structure_remove_field (structure, "endianness");
- gst_structure_remove_field (structure, "depth");
- gst_structure_remove_field (structure, "bpp");
- gst_structure_remove_field (structure, "red_mask");
- gst_structure_remove_field (structure, "green_mask");
- gst_structure_remove_field (structure, "blue_mask");
- gst_structure_remove_field (structure, "alpha_mask");
-
- /* Reuse intersection with Xcontext */
- gst_caps_unref (intersection);
- intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
-
- if (gst_caps_is_empty (intersection)) {
- /* Now try with RGB */
- gst_structure_set_name (structure, "video/x-raw-rgb");
- /* And interset again */
- gst_caps_unref (intersection);
- intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps);
-
- if (gst_caps_is_empty (intersection)) {
- GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with "
- "caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT
- " are completely incompatible with those caps", new_caps,
- xvimagesink->xcontext->caps);
- gst_caps_unref (new_caps);
- ret = GST_FLOW_UNEXPECTED;
- goto beach;
- }
- }
-
- /* Clean this copy */
- gst_caps_unref (new_caps);
- /* We want fixed caps */
- gst_caps_truncate (intersection);
-
- GST_DEBUG_OBJECT (xvimagesink, "allocating a buffer with caps %"
- GST_PTR_FORMAT, intersection);
- } else if (gst_caps_is_equal (intersection, caps)) {
- /* Things work better if we return a buffer with the same caps ptr
- * as was asked for when we can */
- gst_caps_replace (&intersection, caps);
- }
-
- /* Get image format from caps */
- image_format = gst_xvimagesink_get_format_from_caps (xvimagesink,
- intersection);
-
- /* Store our caps and format as the last_caps to avoid expensive
- * caps intersection next time */
- gst_caps_replace (&xvimagesink->xcontext->last_caps, intersection);
- xvimagesink->xcontext->last_format = image_format;
-
-reuse_last_caps:
-
- /* Get geometry from caps */
- structure = gst_caps_get_structure (intersection, 0);
- if (!gst_structure_get_int (structure, "width", &width) ||
- !gst_structure_get_int (structure, "height", &height) ||
- image_format == -1) {
- GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %"
- GST_PTR_FORMAT, intersection);
- ret = GST_FLOW_UNEXPECTED;
- goto beach;
- }
-
- g_mutex_lock (xvimagesink->pool_lock);
-
- /* Walking through the pool cleaning unusable images and searching for a
- suitable one */
- while (xvimagesink->image_pool) {
- xvimage = xvimagesink->image_pool->data;
-
- if (xvimage) {
- /* Removing from the pool */
- xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
- xvimagesink->image_pool);
-
- /* We check for geometry or image format changes */
- if ((xvimage->width != width) ||
- (xvimage->height != height) || (xvimage->im_format != image_format)) {
- /* This image is unusable. Destroying... */
- gst_xvimage_buffer_free (xvimage);
- xvimage = NULL;
- } else {
- /* We found a suitable image */
- GST_LOG_OBJECT (xvimagesink, "found usable image in pool");
- break;
- }
- }
- }
-
- g_mutex_unlock (xvimagesink->pool_lock);
-
- if (!xvimage) {
- /* We found no suitable image in the pool. Creating... */
- GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
- xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection);
- if (xvimage && xvimage->size < size) {
- /* This image is unusable. Destroying... */
- gst_xvimage_buffer_free (xvimage);
- xvimage = NULL;
- }
- }
-
- if (xvimage) {
- gst_buffer_set_caps (GST_BUFFER (xvimage), intersection);
- }
-
- *buf = GST_BUFFER (xvimage);
-
-beach:
- if (intersection) {
- gst_caps_unref (intersection);
- }
-
- return ret;
-}
-
-/* Interfaces stuff */
-
-static gboolean
-gst_xvimagesink_interface_supported (GstImplementsInterface * iface, GType type)
-{
- g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY ||
- type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
- return TRUE;
-}
-
-static void
-gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass)
-{
- klass->supported = gst_xvimagesink_interface_supported;
-}
-
-static void
-gst_xvimagesink_navigation_send_event (GstNavigation * navigation,
- GstStructure * structure)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (navigation);
- GstPad *peer;
-
- if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)))) {
- GstEvent *event;
- GstVideoRectangle src, dst, result;
- gdouble x, y, xscale = 1.0, yscale = 1.0;
-
- event = gst_event_new_navigation (structure);
-
- /* We take the flow_lock while we look at the window */
- g_mutex_lock (xvimagesink->flow_lock);
-
- if (!xvimagesink->xwindow) {
- g_mutex_unlock (xvimagesink->flow_lock);
- return;
- }
-
- /* We get the frame position using the calculated geometry from _setcaps
- that respect pixel aspect ratios */
- src.w = GST_VIDEO_SINK_WIDTH (xvimagesink);
- src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
- dst.w = xvimagesink->xwindow->width;
- dst.h = xvimagesink->xwindow->height;
-
- g_mutex_unlock (xvimagesink->flow_lock);
-
- if (xvimagesink->keep_aspect) {
- gst_video_sink_center_rect (src, dst, &result, TRUE);
- } else {
- result.x = result.y = 0;
- result.w = dst.w;
- result.h = dst.h;
- }
-
- /* We calculate scaling using the original video frames geometry to include
- pixel aspect ratio scaling. */
- xscale = (gdouble) xvimagesink->video_width / result.w;
- yscale = (gdouble) xvimagesink->video_height / result.h;
-
- /* Converting pointer coordinates to the non scaled geometry */
- if (gst_structure_get_double (structure, "pointer_x", &x)) {
- x = MIN (x, result.x + result.w);
- x = MAX (x - result.x, 0);
- gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
- (gdouble) x * xscale, NULL);
- }
- if (gst_structure_get_double (structure, "pointer_y", &y)) {
- y = MIN (y, result.y + result.h);
- y = MAX (y - result.y, 0);
- gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
- (gdouble) y * yscale, NULL);
- }
-
- gst_pad_send_event (peer, event);
- gst_object_unref (peer);
- }
-}
-
-static void
-gst_xvimagesink_navigation_init (GstNavigationInterface * iface)
-{
- iface->send_event = gst_xvimagesink_navigation_send_event;
-}
-
-static void
-gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
- GstXWindow *xwindow = NULL;
- XWindowAttributes attr;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- g_mutex_lock (xvimagesink->flow_lock);
-
- /* If we already use that window return */
- if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) {
- g_mutex_unlock (xvimagesink->flow_lock);
- return;
- }
-
- /* If the element has not initialized the X11 context try to do so */
- if (!xvimagesink->xcontext &&
- !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) {
- g_mutex_unlock (xvimagesink->flow_lock);
- /* we have thrown a GST_ELEMENT_ERROR now */
- return;
- }
-
- gst_xvimagesink_update_colorbalance (xvimagesink);
-
- /* Clear image pool as the images are unusable anyway */
- gst_xvimagesink_imagepool_clear (xvimagesink);
-
- /* Clear the xvimage */
- if (xvimagesink->xvimage) {
- gst_xvimage_buffer_free (xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- }
-
- /* If a window is there already we destroy it */
- if (xvimagesink->xwindow) {
- gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
- xvimagesink->xwindow = NULL;
- }
-
- /* If the xid is 0 we go back to an internal window */
- if (xwindow_id == 0) {
- /* If no width/height caps nego did not happen window will be created
- during caps nego then */
- if (GST_VIDEO_SINK_WIDTH (xvimagesink)
- && GST_VIDEO_SINK_HEIGHT (xvimagesink)) {
- xwindow =
- gst_xvimagesink_xwindow_new (xvimagesink,
- GST_VIDEO_SINK_WIDTH (xvimagesink),
- GST_VIDEO_SINK_HEIGHT (xvimagesink));
- }
- } else {
- xwindow = g_new0 (GstXWindow, 1);
-
- xwindow->win = xwindow_id;
-
- /* We get window geometry, set the event we want to receive,
- and create a GC */
- g_mutex_lock (xvimagesink->x_lock);
- XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr);
- xwindow->width = attr.width;
- xwindow->height = attr.height;
- xwindow->internal = FALSE;
- if (xvimagesink->handle_events) {
- XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask |
- StructureNotifyMask | PointerMotionMask | KeyPressMask |
- KeyReleaseMask);
- }
-
- xwindow->gc = XCreateGC (xvimagesink->xcontext->disp,
- xwindow->win, 0, NULL);
- g_mutex_unlock (xvimagesink->x_lock);
- }
-
- if (xwindow)
- xvimagesink->xwindow = xwindow;
-
- g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_xvimagesink_expose (GstXOverlay * overlay)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
-
- gst_xvimagesink_xvimage_put (xvimagesink, NULL);
-}
-
-static void
-gst_xvimagesink_set_event_handling (GstXOverlay * overlay,
- gboolean handle_events)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
-
- xvimagesink->handle_events = handle_events;
-
- g_mutex_lock (xvimagesink->flow_lock);
-
- if (G_UNLIKELY (!xvimagesink->xwindow)) {
- g_mutex_unlock (xvimagesink->flow_lock);
- return;
- }
-
- g_mutex_lock (xvimagesink->x_lock);
-
- if (handle_events) {
- if (xvimagesink->xwindow->internal) {
- XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
- ExposureMask | StructureNotifyMask | PointerMotionMask |
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask);
- } else {
- XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win,
- ExposureMask | StructureNotifyMask | PointerMotionMask |
- KeyPressMask | KeyReleaseMask);
- }
- } else {
- XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, 0);
- }
-
- g_mutex_unlock (xvimagesink->x_lock);
-
- g_mutex_unlock (xvimagesink->flow_lock);
-}
-
-static void
-gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface)
-{
- iface->set_xwindow_id = gst_xvimagesink_set_xwindow_id;
- iface->expose = gst_xvimagesink_expose;
- iface->handle_events = gst_xvimagesink_set_event_handling;
-}
-
-static const GList *
-gst_xvimagesink_colorbalance_list_channels (GstColorBalance * balance)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- if (xvimagesink->xcontext)
- return xvimagesink->xcontext->channels_list;
- else
- return NULL;
-}
-
-static void
-gst_xvimagesink_colorbalance_set_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel, gint value)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
- g_return_if_fail (channel->label != NULL);
-
- xvimagesink->cb_changed = TRUE;
-
- /* Normalize val to [-1000, 1000] */
- value = -1000 + 2000 * (value - channel->min_value) /
- (channel->max_value - channel->min_value);
-
- if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
- xvimagesink->hue = value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
- xvimagesink->saturation = value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
- xvimagesink->contrast = value;
- } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
- xvimagesink->brightness = value;
- } else {
- g_warning ("got an unknown channel %s", channel->label);
- return;
- }
-
- gst_xvimagesink_update_colorbalance (xvimagesink);
-}
-
-static gint
-gst_xvimagesink_colorbalance_get_value (GstColorBalance * balance,
- GstColorBalanceChannel * channel)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance);
- gint value = 0;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
- g_return_val_if_fail (channel->label != NULL, 0);
-
- if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
- value = xvimagesink->hue;
- } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
- value = xvimagesink->saturation;
- } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
- value = xvimagesink->contrast;
- } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
- value = xvimagesink->brightness;
- } else {
- g_warning ("got an unknown channel %s", channel->label);
- }
-
- /* Normalize val to [channel->min_value, channel->max_value] */
- value = channel->min_value + (channel->max_value - channel->min_value) *
- (value + 1000) / 2000;
-
- return value;
-}
-
-static void
-gst_xvimagesink_colorbalance_init (GstColorBalanceClass * iface)
-{
- GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
- iface->list_channels = gst_xvimagesink_colorbalance_list_channels;
- iface->set_value = gst_xvimagesink_colorbalance_set_value;
- iface->get_value = gst_xvimagesink_colorbalance_get_value;
-}
-
-static const GList *
-gst_xvimagesink_probe_get_properties (GstPropertyProbe * probe)
-{
- GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
- static GList *list = NULL;
-
- if (!list) {
- list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
- }
-
- return list;
-}
-
-static void
-gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
-
- switch (prop_id) {
- case ARG_DEVICE:
- GST_DEBUG_OBJECT (xvimagesink, "probing device list");
- if (!xvimagesink->xcontext) {
- GST_DEBUG_OBJECT (xvimagesink, "generating xcontext");
- xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink);
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
- gboolean ret = FALSE;
-
- switch (prop_id) {
- case ARG_DEVICE:
- if (xvimagesink->xcontext != NULL) {
- ret = FALSE;
- } else {
- ret = TRUE;
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
- return ret;
-}
-
-static GValueArray *
-gst_xvimagesink_probe_get_values (GstPropertyProbe * probe,
- guint prop_id, const GParamSpec * pspec)
-{
- GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe);
- GValueArray *array = NULL;
-
- if (G_UNLIKELY (!xvimagesink->xcontext)) {
- GST_WARNING_OBJECT (xvimagesink, "we don't have any xcontext, can't "
- "get values");
- goto beach;
- }
-
- switch (prop_id) {
- case ARG_DEVICE:
- {
- guint i;
- GValue value = { 0 };
-
- array = g_value_array_new (xvimagesink->xcontext->nb_adaptors);
- g_value_init (&value, G_TYPE_STRING);
-
- for (i = 0; i < xvimagesink->xcontext->nb_adaptors; i++) {
- gchar *adaptor_id_s = g_strdup_printf ("%u", i);
-
- g_value_set_string (&value, adaptor_id_s);
- g_value_array_append (array, &value);
- g_free (adaptor_id_s);
- }
- g_value_unset (&value);
- break;
- }
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
- break;
- }
-
-beach:
- return array;
-}
-
-static void
-gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface *
- iface)
-{
- iface->get_properties = gst_xvimagesink_probe_get_properties;
- iface->probe_property = gst_xvimagesink_probe_probe_property;
- iface->needs_probe = gst_xvimagesink_probe_needs_probe;
- iface->get_values = gst_xvimagesink_probe_get_values;
-}
-
-/* =========================================== */
-/* */
-/* Init & Class init */
-/* */
-/* =========================================== */
-
-static void
-gst_xvimagesink_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstXvImageSink *xvimagesink;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (object));
-
- xvimagesink = GST_XVIMAGESINK (object);
-
- switch (prop_id) {
- case ARG_HUE:
- xvimagesink->hue = g_value_get_int (value);
- xvimagesink->cb_changed = TRUE;
- gst_xvimagesink_update_colorbalance (xvimagesink);
- break;
- case ARG_CONTRAST:
- xvimagesink->contrast = g_value_get_int (value);
- xvimagesink->cb_changed = TRUE;
- gst_xvimagesink_update_colorbalance (xvimagesink);
- break;
- case ARG_BRIGHTNESS:
- xvimagesink->brightness = g_value_get_int (value);
- xvimagesink->cb_changed = TRUE;
- gst_xvimagesink_update_colorbalance (xvimagesink);
- break;
- case ARG_SATURATION:
- xvimagesink->saturation = g_value_get_int (value);
- xvimagesink->cb_changed = TRUE;
- gst_xvimagesink_update_colorbalance (xvimagesink);
- break;
- case ARG_DISPLAY:
- xvimagesink->display_name = g_strdup (g_value_get_string (value));
- break;
- case ARG_SYNCHRONOUS:
- xvimagesink->synchronous = g_value_get_boolean (value);
- if (xvimagesink->xcontext) {
- XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
- GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
- xvimagesink->synchronous ? "TRUE" : "FALSE");
- }
- break;
- case ARG_PIXEL_ASPECT_RATIO:
- g_free (xvimagesink->par);
- xvimagesink->par = g_new0 (GValue, 1);
- g_value_init (xvimagesink->par, GST_TYPE_FRACTION);
- if (!g_value_transform (value, xvimagesink->par)) {
- g_warning ("Could not transform string to aspect ratio");
- gst_value_set_fraction (xvimagesink->par, 1, 1);
- }
- GST_DEBUG_OBJECT (xvimagesink, "set PAR to %d/%d",
- gst_value_get_fraction_numerator (xvimagesink->par),
- gst_value_get_fraction_denominator (xvimagesink->par));
- break;
- case ARG_FORCE_ASPECT_RATIO:
- xvimagesink->keep_aspect = g_value_get_boolean (value);
- break;
- case ARG_HANDLE_EVENTS:
- gst_xvimagesink_set_event_handling (GST_X_OVERLAY (xvimagesink),
- g_value_get_boolean (value));
- break;
- case ARG_DEVICE:
- xvimagesink->adaptor_no = atoi (g_value_get_string (value));
- break;
- case ARG_HANDLE_EXPOSE:
- xvimagesink->handle_expose = g_value_get_boolean (value);
- break;
- case ARG_DOUBLE_BUFFER:
- xvimagesink->double_buffer = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_xvimagesink_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstXvImageSink *xvimagesink;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (object));
-
- xvimagesink = GST_XVIMAGESINK (object);
-
- switch (prop_id) {
- case ARG_HUE:
- g_value_set_int (value, xvimagesink->hue);
- break;
- case ARG_CONTRAST:
- g_value_set_int (value, xvimagesink->contrast);
- break;
- case ARG_BRIGHTNESS:
- g_value_set_int (value, xvimagesink->brightness);
- break;
- case ARG_SATURATION:
- g_value_set_int (value, xvimagesink->saturation);
- break;
- case ARG_DISPLAY:
- g_value_set_string (value, xvimagesink->display_name);
- break;
- case ARG_SYNCHRONOUS:
- g_value_set_boolean (value, xvimagesink->synchronous);
- break;
- case ARG_PIXEL_ASPECT_RATIO:
- if (xvimagesink->par)
- g_value_transform (xvimagesink->par, value);
- break;
- case ARG_FORCE_ASPECT_RATIO:
- g_value_set_boolean (value, xvimagesink->keep_aspect);
- break;
- case ARG_HANDLE_EVENTS:
- g_value_set_boolean (value, xvimagesink->handle_events);
- break;
- case ARG_DEVICE:
- {
- char *adaptor_no_s = g_strdup_printf ("%u", xvimagesink->adaptor_no);
-
- g_value_set_string (value, adaptor_no_s);
- g_free (adaptor_no_s);
- break;
- }
- case ARG_DEVICE_NAME:
- if (xvimagesink->xcontext && xvimagesink->xcontext->adaptors) {
- g_value_set_string (value,
- xvimagesink->xcontext->adaptors[xvimagesink->adaptor_no]);
- } else {
- g_value_set_string (value, NULL);
- }
- break;
- case ARG_HANDLE_EXPOSE:
- g_value_set_boolean (value, xvimagesink->handle_expose);
- break;
- case ARG_DOUBLE_BUFFER:
- g_value_set_boolean (value, xvimagesink->double_buffer);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
-{
- GThread *thread;
-
- GST_OBJECT_LOCK (xvimagesink);
- xvimagesink->running = FALSE;
- /* grab thread and mark it as NULL */
- thread = xvimagesink->event_thread;
- xvimagesink->event_thread = NULL;
- GST_OBJECT_UNLOCK (xvimagesink);
-
- /* Wait for our event thread to finish before we clean up our stuff. */
- if (thread)
- g_thread_join (thread);
-
- if (xvimagesink->cur_image) {
- gst_buffer_unref (xvimagesink->cur_image);
- xvimagesink->cur_image = NULL;
- }
- if (xvimagesink->xvimage) {
- gst_buffer_unref (xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- }
-
- gst_xvimagesink_imagepool_clear (xvimagesink);
-
- if (xvimagesink->xwindow) {
- gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
- gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
- xvimagesink->xwindow = NULL;
- }
-
- gst_xvimagesink_xcontext_clear (xvimagesink);
-}
-
-/* Finalize is called only once, dispose can be called multiple times.
- * We use mutexes and don't reset stuff to NULL here so let's register
- * as a finalize. */
-static void
-gst_xvimagesink_finalize (GObject * object)
-{
- GstXvImageSink *xvimagesink;
-
- xvimagesink = GST_XVIMAGESINK (object);
-
- gst_xvimagesink_reset (xvimagesink);
-
- if (xvimagesink->display_name) {
- g_free (xvimagesink->display_name);
- xvimagesink->display_name = NULL;
- }
-
- if (xvimagesink->par) {
- g_free (xvimagesink->par);
- xvimagesink->par = NULL;
- }
- if (xvimagesink->x_lock) {
- g_mutex_free (xvimagesink->x_lock);
- xvimagesink->x_lock = NULL;
- }
- if (xvimagesink->flow_lock) {
- g_mutex_free (xvimagesink->flow_lock);
- xvimagesink->flow_lock = NULL;
- }
- if (xvimagesink->pool_lock) {
- g_mutex_free (xvimagesink->pool_lock);
- xvimagesink->pool_lock = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_xvimagesink_init (GstXvImageSink * xvimagesink)
-{
- xvimagesink->display_name = NULL;
- xvimagesink->adaptor_no = 0;
- xvimagesink->xcontext = NULL;
- xvimagesink->xwindow = NULL;
- xvimagesink->xvimage = NULL;
- xvimagesink->cur_image = NULL;
-
- xvimagesink->hue = xvimagesink->saturation = 0;
- xvimagesink->contrast = xvimagesink->brightness = 0;
- xvimagesink->cb_changed = FALSE;
-
- xvimagesink->fps_n = 0;
- xvimagesink->fps_d = 0;
- xvimagesink->video_width = 0;
- xvimagesink->video_height = 0;
-
- xvimagesink->x_lock = g_mutex_new ();
- xvimagesink->flow_lock = g_mutex_new ();
-
- xvimagesink->image_pool = NULL;
- xvimagesink->pool_lock = g_mutex_new ();
-
- xvimagesink->synchronous = FALSE;
- xvimagesink->double_buffer = TRUE;
- xvimagesink->running = FALSE;
- xvimagesink->keep_aspect = FALSE;
- xvimagesink->handle_events = TRUE;
- xvimagesink->par = NULL;
- xvimagesink->handle_expose = TRUE;
-}
-
-static void
-gst_xvimagesink_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details (element_class, &gst_xvimagesink_details);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory));
-}
-
-static void
-gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSinkClass *gstbasesink_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
- gstbasesink_class = (GstBaseSinkClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->set_property = gst_xvimagesink_set_property;
- gobject_class->get_property = gst_xvimagesink_get_property;
-
- g_object_class_install_property (gobject_class, ARG_CONTRAST,
- g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
- -1000, 1000, 0, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_BRIGHTNESS,
- g_param_spec_int ("brightness", "Brightness",
- "The brightness of the video", -1000, 1000, 0, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_HUE,
- g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_SATURATION,
- g_param_spec_int ("saturation", "Saturation",
- "The saturation of the video", -1000, 1000, 0, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_DISPLAY,
- g_param_spec_string ("display", "Display", "X Display name", NULL,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_SYNCHRONOUS,
- g_param_spec_boolean ("synchronous", "Synchronous",
- "When enabled, runs "
- "the X display in synchronous mode. (used only for debugging)", FALSE,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_PIXEL_ASPECT_RATIO,
- g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
- "The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_FORCE_ASPECT_RATIO,
- g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
- "When enabled, scaling will respect original aspect ratio", FALSE,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_HANDLE_EVENTS,
- g_param_spec_boolean ("handle-events", "Handle XEvents",
- "When enabled, XEvents will be selected and handled", TRUE,
- G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_DEVICE,
- g_param_spec_string ("device", "Adaptor number",
- "The number of the video adaptor", "0", G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_DEVICE_NAME,
- g_param_spec_string ("device-name", "Adaptor name",
- "The name of the video adaptor", NULL, G_PARAM_READABLE));
- g_object_class_install_property (gobject_class, ARG_HANDLE_EXPOSE,
- g_param_spec_boolean ("handle-expose", "Handle expose", "When enabled, "
- "the current frame will always be drawn in response to X Expose "
- "events", TRUE, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_DOUBLE_BUFFER,
- g_param_spec_boolean ("double-buffer", "Double-buffer",
- "Whether to double-buffer the output", TRUE, G_PARAM_READWRITE));
-
- gobject_class->finalize = gst_xvimagesink_finalize;
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state);
-
- gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
- gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
- gstbasesink_class->buffer_alloc =
- GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
- gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
- gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame);
- gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame);
-}
-
-/* ============================================================= */
-/* */
-/* Public Methods */
-/* */
-/* ============================================================= */
-
-/* =========================================== */
-/* */
-/* Object typing & Creation */
-/* */
-/* =========================================== */
-
-GType
-gst_xvimagesink_get_type (void)
-{
- static GType xvimagesink_type = 0;
-
- if (!xvimagesink_type) {
- static const GTypeInfo xvimagesink_info = {
- sizeof (GstXvImageSinkClass),
- gst_xvimagesink_base_init,
- NULL,
- (GClassInitFunc) gst_xvimagesink_class_init,
- NULL,
- NULL,
- sizeof (GstXvImageSink),
- 0,
- (GInstanceInitFunc) gst_xvimagesink_init,
- };
- static const GInterfaceInfo iface_info = {
- (GInterfaceInitFunc) gst_xvimagesink_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo navigation_info = {
- (GInterfaceInitFunc) gst_xvimagesink_navigation_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo overlay_info = {
- (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo colorbalance_info = {
- (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo propertyprobe_info = {
- (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init,
- NULL,
- NULL,
- };
- xvimagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
- "GstXvImageSink", &xvimagesink_info, 0);
-
- g_type_add_interface_static (xvimagesink_type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_NAVIGATION,
- &navigation_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_X_OVERLAY,
- &overlay_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_COLOR_BALANCE,
- &colorbalance_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
- &propertyprobe_info);
-
-
- /* register type and create class in a more safe place instead of at
- * runtime since the type registration and class creation is not
- * threadsafe. */
- g_type_class_ref (gst_xvimage_buffer_get_type ());
- }
-
- return xvimagesink_type;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "xvimagesink",
- GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK))
- return FALSE;
-
- GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0,
- "xvimagesink element");
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "xvimagesink",
- "XFree86 video output plugin using Xv extension",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_base/sys/xvimage/xvimagesink.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/* GStreamer
- * Copyright (C) <2005> Julien Moutte <julien@moutte.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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_XVIMAGESINK_H__
-#define __GST_XVIMAGESINK_H__
-
-#include <gst/video/gstvideosink.h>
-
-#ifdef HAVE_XSHM
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#ifdef HAVE_XSHM
-#include <X11/extensions/XShm.h>
-#endif /* HAVE_XSHM */
-
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvlib.h>
-
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_XVIMAGESINK \
- (gst_xvimagesink_get_type())
-#define GST_XVIMAGESINK(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XVIMAGESINK, GstXvImageSink))
-#define GST_XVIMAGESINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XVIMAGESINK, GstXvImageSinkClass))
-#define GST_IS_XVIMAGESINK(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIMAGESINK))
-#define GST_IS_XVIMAGESINK_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK))
-
-typedef struct _GstXContext GstXContext;
-typedef struct _GstXWindow GstXWindow;
-typedef struct _GstXvImageFormat GstXvImageFormat;
-typedef struct _GstXvImageBuffer GstXvImageBuffer;
-typedef struct _GstXvImageBufferClass GstXvImageBufferClass;
-
-typedef struct _GstXvImageSink GstXvImageSink;
-typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
-
-/**
- * GstXContext:
- * @disp: the X11 Display of this context
- * @screen: the default Screen of Display @disp
- * @screen_num: the Screen number of @screen
- * @visual: the default Visual of Screen @screen
- * @root: the root Window of Display @disp
- * @white: the value of a white pixel on Screen @screen
- * @black: the value of a black pixel on Screen @screen
- * @depth: the color depth of Display @disp
- * @bpp: the number of bits per pixel on Display @disp
- * @endianness: the endianness of image bytes on Display @disp
- * @width: the width in pixels of Display @disp
- * @height: the height in pixels of Display @disp
- * @widthmm: the width in millimeters of Display @disp
- * @heightmm: the height in millimeters of Display @disp
- * @par: the pixel aspect ratio calculated from @width, @widthmm and @height,
- * @heightmm ratio
- * @use_xshm: used to known wether of not XShm extension is usable or not even
- * if the Extension is present
- * @xv_port_id: the XVideo port ID
- * @im_format: used to store at least a valid format for XShm calls checks
- * @formats_list: list of supported image formats on @xv_port_id
- * @channels_list: list of #GstColorBalanceChannels
- * @caps: the #GstCaps that Display @disp can accept
- *
- * Structure used to store various informations collected/calculated for a
- * Display.
- */
-struct _GstXContext {
- Display *disp;
-
- Screen *screen;
- gint screen_num;
-
- Visual *visual;
-
- Window root;
-
- gulong white, black;
-
- gint depth;
- gint bpp;
- gint endianness;
-
- gint width, height;
- gint widthmm, heightmm;
- GValue *par; /* calculated pixel aspect ratio */
-
- gboolean use_xshm;
-
- XvPortID xv_port_id;
- guint nb_adaptors;
- gchar ** adaptors;
- gint im_format;
-
- GList *formats_list;
- GList *channels_list;
-
- GstCaps *caps;
-
- /* Optimisation storage for buffer_alloc return */
- GstCaps *last_caps;
- gint last_format;
-};
-
-/**
- * GstXWindow:
- * @win: the Window ID of this X11 window
- * @width: the width in pixels of Window @win
- * @height: the height in pixels of Window @win
- * @internal: used to remember if Window @win was created internally or passed
- * through the #GstXOverlay interface
- * @gc: the Graphical Context of Window @win
- *
- * Structure used to store informations about a Window.
- */
-struct _GstXWindow {
- Window win;
- gint width, height;
- gboolean internal;
- GC gc;
-};
-
-/**
- * GstXvImageFormat:
- * @format: the image format
- * @caps: generated #GstCaps for this image format
- *
- * Structure storing image format to #GstCaps association.
- */
-struct _GstXvImageFormat {
- gint format;
- GstCaps *caps;
-};
-
-/**
- * GstXImageBuffer:
- * @xvimagesink: a reference to our #GstXvImageSink
- * @xvimage: the XvImage of this buffer
- * @width: the width in pixels of XvImage @xvimage
- * @height: the height in pixels of XvImage @xvimage
- * @im_format: the image format of XvImage @xvimage
- * @size: the size in bytes of XvImage @xvimage
- *
- * Subclass of #GstBuffer containing additional information about an XvImage.
- */
-struct _GstXvImageBuffer {
- GstBuffer buffer;
-
- /* Reference to the xvimagesink we belong to */
- GstXvImageSink *xvimagesink;
-
- XvImage *xvimage;
-
-#ifdef HAVE_XSHM
- XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
-
- gint width, height, im_format;
- size_t size;
-};
-
-/**
- * GstXvImageSink:
- * @display_name: the name of the Display we want to render to
- * @xcontext: our instance's #GstXContext
- * @xwindow: the #GstXWindow we are rendering to
- * @xvimage: internal #GstXvImage used to store incoming buffers and render when
- * not using the buffer_alloc optimization mechanism
- * @cur_image: a reference to the last #GstXvImage that was put to @xwindow. It
- * is used when Expose events are received to redraw the latest video frame
- * @event_thread: a thread listening for events on @xwindow and handling them
- * @running: used to inform @event_thread if it should run/shutdown
- * @fps_n: the framerate fraction numerator
- * @fps_d: the framerate fraction denominator
- * @x_lock: used to protect X calls as we are not using the XLib in threaded
- * mode
- * @flow_lock: used to protect data flow routines from external calls such as
- * events from @event_thread or methods from the #GstXOverlay interface
- * @par: used to override calculated pixel aspect ratio from @xcontext
- * @pool_lock: used to protect the buffer pool
- * @image_pool: a list of #GstXvImageBuffer that could be reused at next buffer
- * allocation call
- * @synchronous: used to store if XSynchronous should be used or not (for
- * debugging purpose only)
- * @keep_aspect: used to remember if reverse negotiation scaling should respect
- * aspect ratio
- * @handle_events: used to know if we should handle select XEvents or not
- * @brightness: used to store the user settings for color balance brightness
- * @contrast: used to store the user settings for color balance contrast
- * @hue: used to store the user settings for color balance hue
- * @saturation: used to store the user settings for color balance saturation
- * @cb_changed: used to store if the color balance settings where changed
- * @video_width: the width of incoming video frames in pixels
- * @video_height: the height of incoming video frames in pixels
- *
- * The #GstXvImageSink data structure.
- */
-struct _GstXvImageSink {
- /* Our element stuff */
- GstVideoSink videosink;
-
- char *display_name;
- guint adaptor_no;
-
- GstXContext *xcontext;
- GstXWindow *xwindow;
- GstXvImageBuffer *xvimage;
- GstXvImageBuffer *cur_image;
-
- GThread *event_thread;
- gboolean running;
-
- gint fps_n;
- gint fps_d;
-
- GMutex *x_lock;
- GMutex *flow_lock;
-
- /* object-set pixel aspect ratio */
- GValue *par;
-
- GMutex *pool_lock;
- GSList *image_pool;
-
- gboolean synchronous;
- gboolean double_buffer;
- gboolean keep_aspect;
- gboolean draw_border;
- gboolean handle_events;
- gboolean handle_expose;
-
- gint brightness;
- gint contrast;
- gint hue;
- gint saturation;
- gboolean cb_changed;
-
- guint video_width, video_height; /* size of incoming video;
- * used as the size for XvImage */
-};
-
-struct _GstXvImageSinkClass {
- GstVideoSinkClass parent_class;
-};
-
-GType gst_xvimagesink_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_XVIMAGESINK_H__ */
--- a/gst_plugins_good/bwins/libgstcamerabinu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-EXPORTS
- gst_camerabin_get_type @ 1 NONAME
- gst_camerabin_image_get_type @ 2 NONAME
- gst_camerabin_video_get_type @ 3 NONAME
-
--- a/gst_plugins_good/bwins/libgstphotographyu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-EXPORTS
- gst_photography_get_aperture @ 1 NONAME
- gst_photography_get_capabilities @ 2 NONAME
- gst_photography_get_colour_tone_mode @ 3 NONAME
- gst_photography_get_ev_compensation @ 4 NONAME
- gst_photography_get_exposure @ 5 NONAME
- gst_photography_get_flash_mode @ 6 NONAME
- gst_photography_get_iso_speed @ 7 NONAME
- gst_photography_get_scene_mode @ 8 NONAME
- gst_photography_get_type @ 9 NONAME
- gst_photography_get_white_balance_mode @ 10 NONAME
- gst_photography_get_zoom @ 11 NONAME
- gst_photography_prepare_for_capture @ 12 NONAME
- gst_photography_set_aperture @ 13 NONAME
- gst_photography_set_autofocus @ 14 NONAME
- gst_photography_set_colour_tone_mode @ 15 NONAME
- gst_photography_set_ev_compensation @ 16 NONAME
- gst_photography_set_exposure @ 17 NONAME
- gst_photography_set_flash_mode @ 18 NONAME
- gst_photography_set_iso_speed @ 19 NONAME
- gst_photography_set_scene_mode @ 20 NONAME
- gst_photography_set_white_balance_mode @ 21 NONAME
- gst_photography_set_zoom @ 22 NONAME
-
--- a/gst_plugins_good/eabi/libgstcamerabinu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-EXPORTS
- gst_camerabin_get_type @ 1 NONAME
- gst_camerabin_image_get_type @ 2 NONAME
- gst_camerabin_video_get_type @ 3 NONAME
-
--- a/gst_plugins_good/eabi/libgstphotographyu.def Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-EXPORTS
- gst_photography_get_aperture @ 1 NONAME
- gst_photography_get_capabilities @ 2 NONAME
- gst_photography_get_colour_tone_mode @ 3 NONAME
- gst_photography_get_ev_compensation @ 4 NONAME
- gst_photography_get_exposure @ 5 NONAME
- gst_photography_get_flash_mode @ 6 NONAME
- gst_photography_get_iso_speed @ 7 NONAME
- gst_photography_get_scene_mode @ 8 NONAME
- gst_photography_get_type @ 9 NONAME
- gst_photography_get_white_balance_mode @ 10 NONAME
- gst_photography_get_zoom @ 11 NONAME
- gst_photography_prepare_for_capture @ 12 NONAME
- gst_photography_set_aperture @ 13 NONAME
- gst_photography_set_autofocus @ 14 NONAME
- gst_photography_set_colour_tone_mode @ 15 NONAME
- gst_photography_set_ev_compensation @ 16 NONAME
- gst_photography_set_exposure @ 17 NONAME
- gst_photography_set_flash_mode @ 18 NONAME
- gst_photography_set_iso_speed @ 19 NONAME
- gst_photography_set_scene_mode @ 20 NONAME
- gst_photography_set_white_balance_mode @ 21 NONAME
- gst_photography_set_zoom @ 22 NONAME
-
--- a/gst_plugins_good/group/bld.inf Fri May 28 18:11:17 2010 -0500
+++ b/gst_plugins_good/group/bld.inf Fri Jun 25 17:18:46 2010 -0500
@@ -2,8 +2,6 @@
default
PRJ_EXPORTS
-../gst-libs/gst/interfaces/photography.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/photography.h
-../gst-libs/gst/interfaces/photography-enumtypes.h /epoc32/include/platform/mw/gstreamer/gst/interfaces/photography-enumtypes.h
PRJ_MMPFILES
gstwavparse.mmp
@@ -11,7 +9,5 @@
gstautodetect.mmp
gstavi.mmp
gstqtmux.mmp
-gstphotography.mmp
-gstcamerabin.mmp
gstqtdemux.mmp
gstmpegaudioparse.mmp
--- a/gst_plugins_good/group/gstcamerabin.mmp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-// Gstreamer.MMP
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-
-#include <platform_paths.hrh>
-
-TARGET libgstcamerabin.dll
-TARGETTYPE DLL
-//UID 0x20004c45 0x0DE80A1B
-UID 0x20004c45 0x1DE80A1B
-
-LANG SC
-CAPABILITY All -Tcb
-VENDORID VID_DEFAULT
-
-#if !defined(__WINSCW__) && !defined(__WINS__)
-EpocAllowDllData
-#endif
-
-MACRO HAVE_CONFIG_H
-
-USERINCLUDE ..
-USERINCLUDE ../gst/camerabin
-USERINCLUDE ../gst-libs
-USERINCLUDE ../gst-libs/gst
-USERINCLUDE ../gst-libs/gst/interfaces
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-OS_LAYER_GLIB_SYSTEMINCLUDE
-MW_LAYER_GSTREAMER_SYSTEMINCLUDE
-
-SYSTEMINCLUDE ..
-
-
-SOURCEPATH ../gst/camerabin
-SOURCE gstcamerabin.c
-SOURCE gstcamerabinxoverlay.c
-SOURCE gstcamerabincolorbalance.c
-SOURCE camerabinimage.c
-SOURCE camerabinvideo.c
-SOURCE camerabingeneral.c
-SOURCE gstcamerabinphotography.c
-SOURCE gstcamerabin-marshal.c
-
-LIBRARY libc.lib
-LIBRARY libpthread.lib
-LIBRARY libdl.lib
-LIBRARY libglib.lib
-LIBRARY libgmodule.lib
-
-LIBRARY libgobject.lib
-LIBRARY libgthread.lib
-LIBRARY libm.lib
-LIBRARY libz.lib
-LIBRARY libgstreamer.lib
-LIBRARY libgstbase.lib
-LIBRARY libgstinterfaces.lib
-LIBRARY libgstphotography.lib
-
-#ifdef WINSCW
-LIBRARY ewsd.lib //wsd solution
-#endif
-
-
--- a/gst_plugins_good/group/gstphotography.mmp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-
-#include <platform_paths.hrh>
-
-TARGET libgstphotography.dll
-TARGETTYPE DLL
-//UID 0x1000008d 0x10207C43
-// FIX ME change UID
-UID 0x1000008d 0x20207C43
-
-LANG SC
-CAPABILITY All -Tcb
-VENDORID VID_DEFAULT
-
-#if !defined(__WINSCW__) && !defined(__WINS__)
-EpocAllowDllData
-#endif
-
-MACRO HAVE_CONFIG_H
-
-USERINCLUDE ..
-USERINCLUDE ../gst-libs/gst/interfaces
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-OS_LAYER_GLIB_SYSTEMINCLUDE
-
-MW_LAYER_GSTREAMER_SYSTEMINCLUDE
-
-SOURCEPATH ../gst-libs/gst/interfaces
-SOURCE photography.c
-SOURCE photography-enumtypes.c
-
-
-LIBRARY libc.lib
-LIBRARY libpthread.lib
-LIBRARY libdl.lib
-LIBRARY libglib.lib
-LIBRARY libgmodule.lib
-
-LIBRARY libgobject.lib
-LIBRARY libgthread.lib
-LIBRARY libgstreamer.lib
--- a/gst_plugins_good/gst-libs/gst/interfaces/photography-enumtypes.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#include "photography-enumtypes.h"
-
-#include "photography.h"
-
-/* enumerations from "photography.h" */
-GType
-gst_white_balance_mode_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_WB_MODE_AUTO, "GST_PHOTOGRAPHY_WB_MODE_AUTO", "auto"},
- {GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT, "GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT",
- "daylight"},
- {GST_PHOTOGRAPHY_WB_MODE_CLOUDY, "GST_PHOTOGRAPHY_WB_MODE_CLOUDY",
- "cloudy"},
- {GST_PHOTOGRAPHY_WB_MODE_SUNSET, "GST_PHOTOGRAPHY_WB_MODE_SUNSET",
- "sunset"},
- {GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN, "GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN",
- "tungsten"},
- {GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT,
- "GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT", "fluorescent"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstWhiteBalanceMode", values);
- }
- return etype;
-}
-
-GType
-gst_colour_tone_mode_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL", "normal"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SEPIA,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SEPIA", "sepia"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NEGATIVE,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NEGATIVE", "negative"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_GRAYSCALE,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_GRAYSCALE", "grayscale"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NATURAL,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NATURAL", "natural"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_VIVID,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_VIVID", "vivid"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_COLORSWAP,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_COLORSWAP", "colorswap"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SOLARIZE,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SOLARIZE", "solarize"},
- {GST_PHOTOGRAPHY_COLOUR_TONE_MODE_OUT_OF_FOCUS,
- "GST_PHOTOGRAPHY_COLOUR_TONE_MODE_OUT_OF_FOCUS", "out-of-focus"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstColourToneMode", values);
- }
- return etype;
-}
-
-GType
-gst_scene_mode_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_SCENE_MODE_MANUAL, "GST_PHOTOGRAPHY_SCENE_MODE_MANUAL",
- "manual"},
- {GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP, "GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP",
- "closeup"},
- {GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT,
- "GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT", "portrait"},
- {GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE,
- "GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE", "landscape"},
- {GST_PHOTOGRAPHY_SCENE_MODE_SPORT, "GST_PHOTOGRAPHY_SCENE_MODE_SPORT",
- "sport"},
- {GST_PHOTOGRAPHY_SCENE_MODE_NIGHT, "GST_PHOTOGRAPHY_SCENE_MODE_NIGHT",
- "night"},
- {GST_PHOTOGRAPHY_SCENE_MODE_AUTO, "GST_PHOTOGRAPHY_SCENE_MODE_AUTO",
- "auto"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstSceneMode", values);
- }
- return etype;
-}
-
-GType
-gst_flash_mode_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_FLASH_MODE_AUTO, "GST_PHOTOGRAPHY_FLASH_MODE_AUTO",
- "auto"},
- {GST_PHOTOGRAPHY_FLASH_MODE_OFF, "GST_PHOTOGRAPHY_FLASH_MODE_OFF", "off"},
- {GST_PHOTOGRAPHY_FLASH_MODE_ON, "GST_PHOTOGRAPHY_FLASH_MODE_ON", "on"},
- {GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN, "GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN",
- "fill-in"},
- {GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE, "GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE",
- "red-eye"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstFlashMode", values);
- }
- return etype;
-}
-
-GType
-gst_focus_status_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_FOCUS_STATUS_NONE, "GST_PHOTOGRAPHY_FOCUS_STATUS_NONE",
- "none"},
- {GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING,
- "GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING", "running"},
- {GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL, "GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL",
- "fail"},
- {GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS,
- "GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS", "success"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstFocusStatus", values);
- }
- return etype;
-}
-
-GType
-gst_photo_caps_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GFlagsValue values[] = {
- {GST_PHOTOGRAPHY_CAPS_NONE, "GST_PHOTOGRAPHY_CAPS_NONE", "none"},
- {GST_PHOTOGRAPHY_CAPS_EV_COMP, "GST_PHOTOGRAPHY_CAPS_EV_COMP", "ev-comp"},
- {GST_PHOTOGRAPHY_CAPS_ISO_SPEED, "GST_PHOTOGRAPHY_CAPS_ISO_SPEED",
- "iso-speed"},
- {GST_PHOTOGRAPHY_CAPS_WB_MODE, "GST_PHOTOGRAPHY_CAPS_WB_MODE", "wb-mode"},
- {GST_PHOTOGRAPHY_CAPS_TONE, "GST_PHOTOGRAPHY_CAPS_TONE", "tone"},
- {GST_PHOTOGRAPHY_CAPS_SCENE, "GST_PHOTOGRAPHY_CAPS_SCENE", "scene"},
- {GST_PHOTOGRAPHY_CAPS_FLASH, "GST_PHOTOGRAPHY_CAPS_FLASH", "flash"},
- {GST_PHOTOGRAPHY_CAPS_ZOOM, "GST_PHOTOGRAPHY_CAPS_ZOOM", "zoom"},
- {GST_PHOTOGRAPHY_CAPS_FOCUS, "GST_PHOTOGRAPHY_CAPS_FOCUS", "focus"},
- {GST_PHOTOGRAPHY_CAPS_APERTURE, "GST_PHOTOGRAPHY_CAPS_APERTURE",
- "aperture"},
- {GST_PHOTOGRAPHY_CAPS_EXPOSURE, "GST_PHOTOGRAPHY_CAPS_EXPOSURE",
- "exposure"},
- {GST_PHOTOGRAPHY_CAPS_SHAKE, "GST_PHOTOGRAPHY_CAPS_SHAKE", "shake"},
- {0, NULL, NULL}
- };
- etype = g_flags_register_static ("GstPhotoCaps", values);
- }
- return etype;
-}
-
-GType
-gst_photo_shake_risk_get_type (void)
-{
- static GType etype = 0;
- if (etype == 0) {
- static const GEnumValue values[] = {
- {GST_PHOTOGRAPHY_SHAKE_RISK_LOW, "GST_PHOTOGRAPHY_SHAKE_RISK_LOW", "low"},
- {GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM, "GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM",
- "medium"},
- {GST_PHOTOGRAPHY_SHAKE_RISK_HIGH, "GST_PHOTOGRAPHY_SHAKE_RISK_HIGH",
- "high"},
- {0, NULL, NULL}
- };
- etype = g_enum_register_static ("GstPhotoShakeRisk", values);
- }
- return etype;
-}
-
-/* Generated data ends here */
--- a/gst_plugins_good/gst-libs/gst/interfaces/photography-enumtypes.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-
-/* Generated data (by glib-mkenums) */
-
-#ifndef __GST_PHOTOGRAPHY_ENUM_TYPES_H__
-#define __GST_PHOTOGRAPHY_ENUM_TYPES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* enumerations from "photography.h" */
-GType gst_white_balance_mode_get_type (void);
-#define GST_TYPE_WHITE_BALANCE_MODE (gst_white_balance_mode_get_type())
-GType gst_colour_tone_mode_get_type (void);
-#define GST_TYPE_COLOUR_TONE_MODE (gst_colour_tone_mode_get_type())
-GType gst_scene_mode_get_type (void);
-#define GST_TYPE_SCENE_MODE (gst_scene_mode_get_type())
-GType gst_flash_mode_get_type (void);
-#define GST_TYPE_FLASH_MODE (gst_flash_mode_get_type())
-GType gst_focus_status_get_type (void);
-#define GST_TYPE_FOCUS_STATUS (gst_focus_status_get_type())
-GType gst_photo_caps_get_type (void);
-#define GST_TYPE_PHOTO_CAPS (gst_photo_caps_get_type())
-GType gst_photo_shake_risk_get_type (void);
-#define GST_TYPE_PHOTO_SHAKE_RISK (gst_photo_shake_risk_get_type())
-G_END_DECLS
-
-#endif /* __GST_PHOTOGRAPHY_ENUM_TYPES_H__ */
-
-/* Generated data ends here */
-
--- a/gst_plugins_good/gst-libs/gst/interfaces/photography.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * photography.c: photography interface for digital imaging
- *
- *
- * 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 "photography.h"
-
-/**
- * SECTION:photography
- * @short_description: Interface for elements having digital imaging controls
- *
- * The interface allows access to some common digital imaging controls
- */
-
-static void gst_photography_iface_init (GstPhotographyInterface * iface);
-
-EXPORT_C GType
-gst_photography_get_type (void)
-{
- static GType gst_photography_type = 0;
-
- if (!gst_photography_type) {
- static const GTypeInfo gst_photography_info = {
- sizeof (GstPhotographyInterface),
- (GBaseInitFunc) gst_photography_iface_init,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- 0,
- NULL,
- };
-
- gst_photography_type = g_type_register_static (G_TYPE_INTERFACE,
- "GstPhotography", &gst_photography_info, 0);
- g_type_interface_add_prerequisite (gst_photography_type,
- GST_TYPE_IMPLEMENTS_INTERFACE);
- }
-
- return gst_photography_type;
-}
-
-static void
-gst_photography_iface_init (GstPhotographyInterface * iface)
-{
- /* default virtual functions */
- iface->get_ev_compensation = NULL;
- iface->get_iso_speed = NULL;
- iface->get_aperture = NULL;
- iface->get_exposure = NULL;
- iface->get_white_balance_mode = NULL;
- iface->get_colour_tone_mode = NULL;
- iface->get_scene_mode = NULL;
- iface->get_flash_mode = NULL;
- iface->get_zoom = NULL;
-
- iface->set_ev_compensation = NULL;
- iface->set_iso_speed = NULL;
- iface->set_aperture = NULL;
- iface->set_exposure = NULL;
- iface->set_white_balance_mode = NULL;
- iface->set_colour_tone_mode = NULL;
- iface->set_scene_mode = NULL;
- iface->set_flash_mode = NULL;
- iface->set_zoom = NULL;
-
- iface->get_capabilities = NULL;
- iface->prepare_for_capture = NULL;
- iface->set_autofocus = NULL;
-}
-
-#define GST_PHOTOGRAPHY_FUNC_TEMPLATE(function_name, param_type) \
-EXPORT_C gboolean \
-gst_photography_set_ ## function_name (GstPhotography * photo, param_type param) \
-{ \
- GstPhotographyInterface *iface; \
- g_return_val_if_fail (photo != NULL, FALSE); \
- iface = GST_PHOTOGRAPHY_GET_IFACE (photo); \
- if (iface->set_ ## function_name) { \
- return iface->set_ ## function_name (photo, param); \
- } \
- return FALSE; \
-} \
-EXPORT_C gboolean \
-gst_photography_get_ ## function_name (GstPhotography * photo, param_type * param) \
-{ \
- GstPhotographyInterface *iface; \
- g_return_val_if_fail (photo != NULL, FALSE); \
- iface = GST_PHOTOGRAPHY_GET_IFACE (photo); \
- if (iface->get_ ## function_name) { \
- return iface->get_ ## function_name (photo, param); \
- } \
- return FALSE; \
-}
-
-
-/**
- * gst_photography_set_ev_compensation:
- * @photo: #GstPhotography interface of a #GstElement
- * @ev_comp: ev compensation value to set
- *
- * Set the ev compensation value for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_ev_compensation:
- * @photo: #GstPhotography interface of a #GstElement
- * @ev_comp: ev compensation value to get
- *
- * Get the ev compensation value for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (ev_compensation, gfloat);
-
-/**
- * gst_photography_set_iso_speed:
- * @photo: #GstPhotography interface of a #GstElement
- * @iso_speed: ISO speed value to set
- *
- * Set the ISO value (light sensivity) for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_iso_speed:
- * @photo: #GstPhotography interface of a #GstElement
- * @iso_speed: ISO speed value to get
- *
- * Get the ISO value (light sensivity) for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (iso_speed, guint);
-
-/**
- * gst_photography_set_aperture:
- * @photo: #GstPhotography interface of a #GstElement
- * @aperture: aperture value to set
- *
- * Set the aperture value for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_aperture:
- * @photo: #GstPhotography interface of a #GstElement
- * @aperture: aperture value to get
- *
- * Get the aperture value for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (aperture, guint);
-
-/**
- * gst_photography_set_exposure:
- * @photo: #GstPhotography interface of a #GstElement
- * @exposure: exposure time to set
- *
- * Set the fixed exposure time (in us) for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_exposure:
- * @photo: #GstPhotography interface of a #GstElement
- * @exposure: exposure time to get
- *
- * Get the fixed exposure time (in us) for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (exposure, guint32);
-
-/**
- * gst_photography_set_white_balance_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @wb_mode: #GstWhiteBalanceMode to set
- *
- * Set the white balance mode for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_white_balance_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @wb_mode: #GstWhiteBalanceMode to get
- *
- * Get the white balance mode for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (white_balance_mode, GstWhiteBalanceMode);
-
-/**
- * gst_photography_set_colour_tone_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @tone_mode: #GstColourToneMode to set
- *
- * Set the colour tone mode for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_colour_tone_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @tone_mode: #GstColourToneMode to get
- *
- * Get the colour tone mode for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (colour_tone_mode, GstColourToneMode);
-
-/**
- * gst_photography_set_scene_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @scene_mode: #GstSceneMode to set
- *
- * Set the scene mode for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_scene_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @scene_mode: #GstSceneMode to get
- *
- * Get the scene mode for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (scene_mode, GstSceneMode);
-
-/**
- * gst_photography_set_flash_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @flash_mode: #GstFlashMode to set
- *
- * Set the flash mode for the #GstElement
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_flash_mode:
- * @photo: #GstPhotography interface of a #GstElement
- * @flash_mode: #GstFlashMode to get
- *
- * Get the flash mode for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (flash_mode, GstFlashMode);
-
-/**
- * gst_photography_set_zoom:
- * @photo: #GstPhotography interface of a #GstElement
- * @zoom: zoom value to set
- *
- * Set the zoom value for the #GstElement.
- * E.g. 1.0 to get original image and 3.0 for 3x zoom and so on.
- *
- * Returns: %TRUE if setting the value succeeded, %FALSE otherwise
- */
-/**
- * gst_photography_get_zoom:
- * @photo: #GstPhotography interface of a #GstElement
- * @zoom: zoom value to get
- *
- * Get the zoom value for the #GstElement
- *
- * Returns: %TRUE if getting the value succeeded, %FALSE otherwise
- */
-GST_PHOTOGRAPHY_FUNC_TEMPLATE (zoom, gfloat);
-
-/**
- * gst_photography_get_capabilities:
- * @photo: #GstPhotography interface of a #GstElement
- *
- * Get #GstPhotoCaps bitmask value that indicates what photography
- * interface features the #GstElement supports
- *
- * Returns: #GstPhotoCaps value
- */
-EXPORT_C
-GstPhotoCaps
-gst_photography_get_capabilities (GstPhotography * photo)
-{
- GstPhotographyInterface *iface;
- g_return_val_if_fail (photo != NULL, GST_PHOTOGRAPHY_CAPS_NONE);
-
- iface = GST_PHOTOGRAPHY_GET_IFACE (photo);
- if (iface->get_capabilities) {
- return iface->get_capabilities (photo);
- } else {
- return GST_PHOTOGRAPHY_CAPS_NONE;
- }
-}
-
-/**
- * gst_photography_prepare_for_capture:
- * @photo: #GstPhotography interface of a #GstElement
- * @func: callback that is called after capturing has been prepared
- * @user_data: user data that will be passed to the callback @func
- *
- * Start preparations for capture. @func callback is called after
- * preparations are done.
- */
-EXPORT_C
-void
-gst_photography_prepare_for_capture (GstPhotography * photo,
- GstPhotoCapturePrepared func, gpointer user_data)
-{
- GstPhotographyInterface *iface;
- g_return_if_fail (photo != NULL);
-
- iface = GST_PHOTOGRAPHY_GET_IFACE (photo);
- if (iface->prepare_for_capture) {
- iface->prepare_for_capture (photo, func, user_data);
- }
-}
-
-/**
- * gst_photography_set_autofocus:
- * @photo: #GstPhotography interface of a #GstElement
- * @on: %TRUE to start autofocusing, %FALSE to stop autofocusing
- *
- * Start or stop autofocusing. %GST_PHOTOGRAPHY_AUTOFOCUS_DONE
- * message is posted to bus when autofocusing has finished.
- */
-EXPORT_C
-void
-gst_photography_set_autofocus (GstPhotography * photo, gboolean on)
-{
- GstPhotographyInterface *iface;
- g_return_if_fail (photo != NULL);
-
- iface = GST_PHOTOGRAPHY_GET_IFACE (photo);
- if (iface->set_autofocus) {
- iface->set_autofocus (photo, on);
- }
-}
--- a/gst_plugins_good/gst-libs/gst/interfaces/photography.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-/* GStreamer
- *
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * photography.h: photography interface for digital imaging
- *
- *
- * 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 __GST_PHOTOGRAPHY_H__
-#define __GST_PHOTOGRAPHY_H__
-
-#include <gst/gst.h>
-#include <gst/interfaces/photography-enumtypes.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_PHOTOGRAPHY \
- (gst_photography_get_type ())
-#define GST_PHOTOGRAPHY(obj) \
- (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PHOTOGRAPHY, GstPhotography))
-#define GST_IS_PHOTOGRAPHY(obj) \
- (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PHOTOGRAPHY))
-#define GST_PHOTOGRAPHY_GET_IFACE(inst) \
- (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_PHOTOGRAPHY, GstPhotographyInterface))
-
-
-/* Custom GstMessage name that will be sent to GstBus when autofocusing
- is complete */
-#define GST_PHOTOGRAPHY_AUTOFOCUS_DONE "autofocus-done"
-
-/* Custom GstMessage name that will be sent to GstBus when shake risk changes */
-#define GST_PHOTOGRAPHY_SHAKE_RISK "shake-risk"
-
-/**
- * GstPhotography:
- *
- * Opaque #GstPhotography data structure.
- */
-typedef struct _GstPhotography GstPhotography;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_WB_MODE_AUTO = 0,
- GST_PHOTOGRAPHY_WB_MODE_DAYLIGHT,
- GST_PHOTOGRAPHY_WB_MODE_CLOUDY,
- GST_PHOTOGRAPHY_WB_MODE_SUNSET,
- GST_PHOTOGRAPHY_WB_MODE_TUNGSTEN,
- GST_PHOTOGRAPHY_WB_MODE_FLUORESCENT
-} GstWhiteBalanceMode;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NORMAL = 0,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SEPIA,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NEGATIVE,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_GRAYSCALE,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_NATURAL,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_VIVID,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_COLORSWAP,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_SOLARIZE,
- GST_PHOTOGRAPHY_COLOUR_TONE_MODE_OUT_OF_FOCUS
-} GstColourToneMode;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_SCENE_MODE_MANUAL = 0,
- GST_PHOTOGRAPHY_SCENE_MODE_CLOSEUP,
- GST_PHOTOGRAPHY_SCENE_MODE_PORTRAIT,
- GST_PHOTOGRAPHY_SCENE_MODE_LANDSCAPE,
- GST_PHOTOGRAPHY_SCENE_MODE_SPORT,
- GST_PHOTOGRAPHY_SCENE_MODE_NIGHT,
- GST_PHOTOGRAPHY_SCENE_MODE_AUTO
-} GstSceneMode;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_FLASH_MODE_AUTO = 0,
- GST_PHOTOGRAPHY_FLASH_MODE_OFF,
- GST_PHOTOGRAPHY_FLASH_MODE_ON,
- GST_PHOTOGRAPHY_FLASH_MODE_FILL_IN,
- GST_PHOTOGRAPHY_FLASH_MODE_RED_EYE
-} GstFlashMode;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_FOCUS_STATUS_NONE = 0,
- GST_PHOTOGRAPHY_FOCUS_STATUS_RUNNING,
- GST_PHOTOGRAPHY_FOCUS_STATUS_FAIL,
- GST_PHOTOGRAPHY_FOCUS_STATUS_SUCCESS
-} GstFocusStatus;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_CAPS_NONE = (0 << 0),
- GST_PHOTOGRAPHY_CAPS_EV_COMP = (1 << 0),
- GST_PHOTOGRAPHY_CAPS_ISO_SPEED = (1 << 1),
- GST_PHOTOGRAPHY_CAPS_WB_MODE = (1 << 2),
- GST_PHOTOGRAPHY_CAPS_TONE = (1 << 3),
- GST_PHOTOGRAPHY_CAPS_SCENE = (1 << 4),
- GST_PHOTOGRAPHY_CAPS_FLASH = (1 << 5),
- GST_PHOTOGRAPHY_CAPS_ZOOM = (1 << 6),
- GST_PHOTOGRAPHY_CAPS_FOCUS = (1 << 7),
- GST_PHOTOGRAPHY_CAPS_APERTURE = (1 << 8),
- GST_PHOTOGRAPHY_CAPS_EXPOSURE = (1 << 9),
- GST_PHOTOGRAPHY_CAPS_SHAKE = (1 << 10)
-} GstPhotoCaps;
-
-typedef enum
-{
- GST_PHOTOGRAPHY_SHAKE_RISK_LOW = 0,
- GST_PHOTOGRAPHY_SHAKE_RISK_MEDIUM,
- GST_PHOTOGRAPHY_SHAKE_RISK_HIGH,
-} GstPhotoShakeRisk;
-
-typedef struct
-{
- GstWhiteBalanceMode wb_mode;
- GstColourToneMode tone_mode;
- GstSceneMode scene_mode;
- GstFlashMode flash_mode;
- guint32 exposure;
- guint aperture;
- gfloat ev_compensation;
- guint iso_speed;
- gfloat zoom;
-} GstPhotoSettings;
-
-/**
- * GstPhotoCapturePrepared:
- * @data: user data that has been given, when registering the callback
- *
- * This callback will be called when the element has finished preparations
- * for photo capture.
- */
-typedef void (*GstPhotoCapturePrepared) (gpointer data);
-
-/**
- * GstPhotographyInterface:
- * @parent: parent interface type.
- * @get_ev_compensation: vmethod to get ev exposure compensation value
- * @get_iso_speed: vmethod to get iso speed (light sensitivity) value
- * @get_aperture: vmethod to get aperture value
- * @get_exposure: vmethod to get exposure time value
- * @get_white_balance_mode: vmethod to get white balance mode value
- * @get_colour_tone_mode: vmethod to get colour tone mode value
- * @get_scene_mode: vmethod to get scene mode value
- * @get_flash_mode: vmethod to get flash mode value
- * @get_zoom: vmethod to get zoom factor value
- * @set_ev_compensation: vmethod to set ev exposure compensation value
- * @set_iso_speed: vmethod to set iso speed (light sensitivity) value
- * @set_aperture: vmethod to set aperture value
- * @set_exposure: vmethod to set exposure time value
- * @set_white_balance_mode: vmethod to set white balance mode value
- * @set_colour_tone_mode: vmethod to set colour tone mode value
- * @set_scene_mode: vmethod to set scene mode value
- * @set_flash_mode: vmethod to set flash mode value
- * @set_zoom: vmethod to set zoom factor value
- * @get_capabilities: vmethod to get supported capabilities of the interface
- * @prepare_for_capture: vmethod to tell the element to prepare for capturing
- * @set_autofocus: vmethod to set autofocus on/off
- *
- * #GstPhotographyInterface interface.
- */
-typedef struct _GstPhotographyInterface
-{
- GTypeInterface parent;
-
- /* virtual functions */
- gboolean (*get_ev_compensation) (GstPhotography * photo, gfloat * ev_comp);
- gboolean (*get_iso_speed) (GstPhotography * photo, guint * iso_speed);
- gboolean (*get_aperture) (GstPhotography * photo, guint * aperture);
- gboolean (*get_exposure) (GstPhotography * photo, guint32 * exposure);
- gboolean (*get_white_balance_mode) (GstPhotography * photo,
- GstWhiteBalanceMode * wb_mode);
- gboolean (*get_colour_tone_mode) (GstPhotography * photo,
- GstColourToneMode * tone_mode);
- gboolean (*get_scene_mode) (GstPhotography * photo,
- GstSceneMode * scene_mode);
- gboolean (*get_flash_mode) (GstPhotography * photo,
- GstFlashMode * flash_mode);
- gboolean (*get_zoom) (GstPhotography * photo, gfloat * zoom);
-
- gboolean (*set_ev_compensation) (GstPhotography * photo, gfloat ev_comp);
- gboolean (*set_iso_speed) (GstPhotography * photo, guint iso_speed);
- gboolean (*set_aperture) (GstPhotography * photo, guint aperture);
- gboolean (*set_exposure) (GstPhotography * photo, guint32 exposure);
- gboolean (*set_white_balance_mode) (GstPhotography * photo,
- GstWhiteBalanceMode wb_mode);
- gboolean (*set_colour_tone_mode) (GstPhotography * photo,
- GstColourToneMode tone_mode);
- gboolean (*set_scene_mode) (GstPhotography * photo,
- GstSceneMode scene_mode);
- gboolean (*set_flash_mode) (GstPhotography * photo,
- GstFlashMode flash_mode);
- gboolean (*set_zoom) (GstPhotography * photo, gfloat zoom);
-
- GstPhotoCaps (*get_capabilities) (GstPhotography * photo);
- void (*prepare_for_capture) (GstPhotography * photo,
- GstPhotoCapturePrepared func, gpointer user_data);
- void (*set_autofocus) (GstPhotography * photo, gboolean on);
-
- /*< private > */
- gpointer _gst_reserved[GST_PADDING];
-} GstPhotographyInterface;
-
-IMPORT_C GType gst_photography_get_type (void);
-
-/* virtual class function wrappers */
-IMPORT_C gboolean gst_photography_get_ev_compensation (GstPhotography * photo,
- gfloat * ev_comp);
-IMPORT_C gboolean gst_photography_get_iso_speed (GstPhotography * photo,
- guint * iso_speed);
-IMPORT_C gboolean gst_photography_get_aperture (GstPhotography * photo,
- guint * aperture);
-IMPORT_C gboolean gst_photography_get_exposure (GstPhotography * photo,
- guint32 * exposure);
-IMPORT_C gboolean gst_photography_get_white_balance_mode (GstPhotography * photo,
- GstWhiteBalanceMode * wb_mode);
-IMPORT_C gboolean gst_photography_get_colour_tone_mode (GstPhotography * photo,
- GstColourToneMode * tone_mode);
-IMPORT_C gboolean gst_photography_get_scene_mode (GstPhotography * photo,
- GstSceneMode * scene_mode);
-IMPORT_C gboolean gst_photography_get_flash_mode (GstPhotography * photo,
- GstFlashMode * flash_mode);
-IMPORT_C gboolean gst_photography_get_zoom (GstPhotography * photo, gfloat * zoom);
-
-IMPORT_C gboolean gst_photography_set_ev_compensation (GstPhotography * photo,
- gfloat ev_comp);
-IMPORT_C gboolean gst_photography_set_iso_speed (GstPhotography * photo,
- guint iso_speed);
-IMPORT_C gboolean gst_photography_set_aperture (GstPhotography * photo, guint aperture);
-IMPORT_C gboolean gst_photography_set_exposure (GstPhotography * photo, guint exposure);
-IMPORT_C gboolean gst_photography_set_white_balance_mode (GstPhotography * photo,
- GstWhiteBalanceMode wb_mode);
-IMPORT_C gboolean gst_photography_set_colour_tone_mode (GstPhotography * photo,
- GstColourToneMode tone_mode);
-IMPORT_C gboolean gst_photography_set_scene_mode (GstPhotography * photo,
- GstSceneMode scene_mode);
-IMPORT_C gboolean gst_photography_set_flash_mode (GstPhotography * photo,
- GstFlashMode flash_mode);
-IMPORT_C gboolean gst_photography_set_zoom (GstPhotography * photo, gfloat zoom);
-
-IMPORT_C GstPhotoCaps gst_photography_get_capabilities (GstPhotography * photo);
-
-IMPORT_C void gst_photography_prepare_for_capture (GstPhotography * photo,
- GstPhotoCapturePrepared func, gpointer user_data);
-
-IMPORT_C void gst_photography_set_autofocus (GstPhotography * photo, gboolean on);
-
-G_END_DECLS
-
-#endif /* __GST_PHOTOGRAPHY_H__ */
--- a/gst_plugins_good/gst/amrmux/gstamrmux.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-/*
- * Copyright © 2010 Nokia Corporation.
- * This material, including documentation and any related
- * computer progrs, is protected by copyright controlled by
- * Nokia Corporation. All rights are reserved. Copying,
- * including reproducing, storing, adapting or translating, any
- * or all of this material requires the prior written consent of
- * Nokia Corporation. This material also contains confidential
- * information which may not be disclosed to others without the
- * prior written consent of Nokia Corporation.
- * ============================================================================
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#include "gstamrmux.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-
-#ifdef __SYMBIAN32__
-#include <gst/gstinfo.h>
-#endif
-
-/* AMR nb header value */
-const char* amrnbmagicnumber = "#!AMR\n";
-
-static void gst_amrmux_base_init (gpointer g_class);
-static void gst_amrmux_class_init (GstAmrMuxClass * klass);
-static void gst_amrmux_init ( GstAmrMux * filter, GstAmrMuxClass *filter_klass);
-
-static GstFlowReturn gst_amrmux_chain (GstPad * pad, GstBuffer * buf);
-
-static void gst_amrmux_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static void gst_amrmux_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec);
-
-static GstStateChangeReturn gst_amrmux_change_state (GstElement * element,
- GstStateChange transition);
-
-static void gst_amrmux_dispose(GObject * object);
-
-static GstElementClass *parent_class= NULL;
-
-static const GstElementDetails gst_amrmux_details =
-GST_ELEMENT_DETAILS ("AMR MUX Details",
- "Codec/Muxer/Audio",
- "Adaptive Multi-Rate Narrow-Band Muxer",
- "");
-
-static GstStaticPadTemplate sink_factory =
-GST_STATIC_PAD_TEMPLATE (
- "sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/amr")
-);
-
-static GstStaticPadTemplate source_factory =
-GST_STATIC_PAD_TEMPLATE (
- "src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/amr")
-);
-
-enum {
- ARG_0,
- ARG_HEADER
-};
-
-
-GType
-gst_amrmux_get_type (void)
-{
- static GType gst_amrmux_type = 0;
-
- if (!gst_amrmux_type) {
- static const GTypeInfo amrmux_info = {
- sizeof (GstAmrMuxClass),
- gst_amrmux_base_init,
- NULL,
- (GClassInitFunc) gst_amrmux_class_init,
- NULL,
- NULL,
- sizeof (GstAmrMux),
- 0,
- (GInstanceInitFunc) gst_amrmux_init,
- };
-
- gst_amrmux_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstAmrMux",
- &amrmux_info, 0);
- }
- return gst_amrmux_type;
-}
-
-
-static void
-gst_amrmux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template(element_class,
- gst_static_pad_template_get(&sink_factory));
-
- gst_element_class_add_pad_template(element_class,
- gst_static_pad_template_get(&source_factory));
-
- gst_element_class_set_details (element_class, &gst_amrmux_details);
-}
-
-static void
-gst_amrmux_class_init ( GstAmrMuxClass * klass )
-{
- GObjectClass *object_class;
- GstElementClass *gstelement_class;
-
- gstelement_class = (GstElementClass *) klass;
- object_class = (GObjectClass *) klass;
-
-
- object_class->set_property = gst_amrmux_set_property;
- object_class->get_property = gst_amrmux_get_property;
-
- gstelement_class->change_state = gst_amrmux_change_state;
-
- object_class->dispose = gst_amrmux_dispose;
-
- parent_class = g_type_class_peek_parent(klass);
-
- g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HEADER,
- g_param_spec_boolean ("header", "header",
- "For writing AMR header", TRUE, G_PARAM_READWRITE));
-
-
- }
-
-static void gst_amrmux_dispose(GObject * object)
-{
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-gst_amrmux_init( GstAmrMux * amrmux, GstAmrMuxClass *amrmux_klass)
-{
- GstElementClass *klass = GST_ELEMENT_CLASS (amrmux_klass);
-
- //By default we have to write header
- amrmux->writeheader= TRUE;
-
- //Add Sink pad to this element
-
- amrmux->sinkpad = gst_pad_new_from_template (
- gst_element_class_get_pad_template (klass, "sink"), "sink");
-
- gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->sinkpad);
-
-
- //Add Src pad to this element
- amrmux->srcpad = gst_pad_new_from_template (
- gst_element_class_get_pad_template (klass, "src"), "src");
-
- gst_element_add_pad (GST_ELEMENT (amrmux), amrmux->srcpad);
-
- gst_pad_set_chain_function (amrmux->sinkpad, gst_amrmux_chain);
-
-}
-
-
-static void
-gst_amrmux_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
-
- GstAmrMux *amrmux = GST_AMRMUX( object );
-
- switch (prop_id) {
- case ARG_HEADER:
- g_value_set_boolean (value, amrmux->writeheader);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-gst_amrmux_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
-GstAmrMux *amrmux = GST_AMRMUX( object );
-
- switch (prop_id) {
- case ARG_HEADER:
- amrmux->writeheader = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-
-static GstFlowReturn
-gst_amrmux_chain (GstPad * pad, GstBuffer * buf)
-{
-
- gint8 *codecdata;
- guint8* amrdata;
- guint8* amrheaderstart;
-
- int codecdatasize = GST_BUFFER_SIZE(buf);
-
- int magicnumberlength = strlen( amrnbmagicnumber );
-
- GstAmrMux *amrmux = GST_AMRMUX (GST_PAD_PARENT (pad));
-
- if ( amrmux->writeheader )
- {
-
- buf = gst_buffer_make_writable( buf );
-
- //Allocate a buffer which will hold codec data + magic number
-
- amrdata = ( guint8* )g_malloc( GST_BUFFER_SIZE(buf) + magicnumberlength );
-
- //To save the starting address of amr data
-
- amrheaderstart = amrdata;
-
- //Copy magic number to newly allocated buffer
-
- memcpy( amrdata, amrnbmagicnumber, magicnumberlength);
-
- codecdata = (gint8*)GST_BUFFER_DATA (buf);
-
- //Move the pointer to the end of magic number
-
- amrdata += magicnumberlength;
-
- //Copy codec data to newly allocated buffer
-
- memcpy( amrdata , codecdata, codecdatasize );
-
- // free codec data from GstBuffer
-
- g_free( buf->malloc_data );
-
- //Copying the newly allocated buffer and size in GstBuffer
-
- buf->data = amrheaderstart;
-
- buf->malloc_data = amrheaderstart;
-
- buf->size+= magicnumberlength;
-
- //Do it only first time
-
- amrmux->writeheader = FALSE;
- }
-
- return gst_pad_push( amrmux->srcpad , buf );
-
-}
-
-static GstStateChangeReturn
-gst_amrmux_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- GstAmrMux *amrmux = GST_AMRMUX (element);
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- if (G_UNLIKELY (ret == GST_STATE_CHANGE_FAILURE))
- return ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_NULL:
- {
- amrmux->writeheader = TRUE;
- break;
- }
-
- default:
- break;
- }
-
- return ret;
-}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
-
- return gst_element_register (plugin, "amrmux", GST_RANK_PRIMARY,
- GST_TYPE_AMRMUX);
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "amrmux",
- "Add header to amr-nb encoded stream",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
-
-
-EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
-{
- return &gst_plugin_desc;
-}
-
--- a/gst_plugins_good/gst/amrmux/gstamrmux.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010 Nokia Corporation.
- * This material, including documentation and any related
- * computer progrs, is protected by copyright controlled by
- * Nokia Corporation. All rights are reserved. Copying,
- * including reproducing, storing, adapting or translating, any
- * or all of this material requires the prior written consent of
- * Nokia Corporation. This material also contains confidential
- * information which may not be disclosed to others without the
- * prior written consent of Nokia Corporation.
- * ============================================================================
- */
-
-
-#ifndef __GST_AMRMUX_H__
-#define __GST_AMRMUX_H__
-
-
-#include <gst/gst.h>
-#include <gst/gst_global.h>
-
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_AMRMUX \
- (gst_amrmux_get_type())
-#define GST_AMRMUX(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AMRMUX,GstAmrMux))
-#define GST_AMRMUX_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AMRMUX,GstAmrMuxClass))
-#define GST_IS_AMRMUX(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AMRMUX))
-#define GST_IS_AMRMUX_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AMRMUX))
-
-
-typedef struct _GstAmrMux GstAmrMux;
-typedef struct _GstAmrMuxClass GstAmrMuxClass;
-
-/**
- * GstAmrMux:
- *
- *
- */
-struct _GstAmrMux {
- GstElement parent;
-
- /* pads */
- GstPad *sinkpad,*srcpad;
-
- /* Flag to decide whether to write amr header or not */
- gboolean writeheader;
-};
-
-struct _GstAmrMuxClass {
- GstElementClass parent_class;
-};
-
-GType gst_amrmux_get_type(void);
-
-G_END_DECLS
-
-#endif /* __GST_AMRMUX_H__ */
--- a/gst_plugins_good/gst/amrmux/gstamrmux.mmp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright © 2010 Nokia Corporation.
- * This material, including documentation and any related
- * computer progrs, is protected by copyright controlled by
- * Nokia Corporation. All rights are reserved. Copying,
- * including reproducing, storing, adapting or translating, any
- * or all of this material requires the prior written consent of
- * Nokia Corporation. This material also contains confidential
- * information which may not be disclosed to others without the
- * prior written consent of Nokia Corporation.
- * ============================================================================
- */
-
-#include <platform_paths.hrh>
-
-TARGET libgstamrmux.dll
-TARGETTYPE DLL
-UID 0x2002C38F 0x2002C390
-
-#ifdef EKA2
-LANG SC
-CAPABILITY All -Tcb
-VENDORID VID_DEFAULT
-
-#endif
-
-#if !defined(__WINSCW__) && !defined(__WINS__)
-EpocAllowDllData
-#endif
-
-MACRO HAVE_CONFIG_H
-
-
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-OS_LAYER_GLIB_SYSTEMINCLUDE
-
-
-USERINCLUDE ../../../include/gstreamer
-USERINCLUDE ../../../include/gstreamer/gst
-USERINCLUDE ../../../include/gstreamer/gst/base
-USERINCLUDE ../../../include/gstreamer/gst/controller
-USERINCLUDE ../../../include/gstreamer/gst/dataprotocol
-USERINCLUDE ../../../include/gstreamer/gst/net
-
-
-
-SOURCEPATH ../gst/amrmux
-SOURCE gstamrmux.c
-
-
-LIBRARY libc.lib
-LIBRARY libglib.lib
-LIBRARY libgmodule.lib
-LIBRARY libgobject.lib
-LIBRARY libgstreamer.lib
-
--- a/gst_plugins_good/gst/camerabin/camerabingeneral.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/**
- * SECTION:camerabingeneral
- * @short_description: helper functions for #GstCameraBin and it's modules
- *
- * Common helper functions for #GstCameraBin, #GstCameraBinImage and
- * #GstCameraBinVideo.
- *
- */
-
-#include "camerabingeneral.h"
-#include <glib.h>
-
-GST_DEBUG_CATEGORY (gst_camerabin_debug);
-
-static gboolean
-camerabin_general_dbg_have_event (GstPad * pad, GstEvent * event,
- gpointer u_data)
-{
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_NEWSEGMENT:
- {
- GstElement *elem = (GstElement *) u_data;
- gchar *elem_name = gst_element_get_name (elem);
- gchar *pad_name = gst_pad_get_name (pad);
-
- gboolean update;
- gdouble rate;
- GstFormat format;
- gint64 start, stop, pos;
- gst_event_parse_new_segment (event, &update, &rate, &format, &start,
- &stop, &pos);
-
- GST_DEBUG ("element %s, pad %s, new_seg_start =%" GST_TIME_FORMAT
- ", new_seg_stop =%" GST_TIME_FORMAT
- ", new_seg_pos =%" GST_TIME_FORMAT "\n", elem_name, pad_name,
- GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos));
-
- g_free (pad_name);
- g_free (elem_name);
- }
- break;
- default:
- break;
- }
-
- return TRUE;
-}
-
-static gboolean
-camerabin_general_dbg_have_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data)
-{
- GstElement *elem = (GstElement *) u_data;
- gchar *elem_name = gst_element_get_name (elem);
- gchar *pad_name = gst_pad_get_name (pad);
-
- GST_DEBUG ("element %s, pad %s, buf_ts =%" GST_TIME_FORMAT "\n", elem_name,
- pad_name, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-
- g_free (pad_name);
- g_free (elem_name);
-
- return TRUE;
-
-}
-
-void
-camerabin_general_dbg_set_probe (GstElement * elem, gchar * pad_name,
- gboolean buf, gboolean evt)
-{
- GstPad *pad = gst_element_get_static_pad (elem, pad_name);
-
- if (buf)
- gst_pad_add_buffer_probe (pad,
- G_CALLBACK (camerabin_general_dbg_have_buffer), elem);
- if (evt)
- gst_pad_add_event_probe (pad,
- G_CALLBACK (camerabin_general_dbg_have_event), elem);
-
- gst_object_unref (pad);
-}
-
-/**
- * gst_camerabin_add_element:
- * @bin: add an element to this bin
- * @new_elem: new element to be added
- *
- * Adds given element to given @bin. Looks for an unconnected src pad
- * from the @bin and links the element to it. Raises an error if adding
- * or linking failed.
- *
- * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise.
- */
-gboolean
-gst_camerabin_add_element (GstBin * bin, GstElement * new_elem)
-{
- gboolean ret = FALSE;
-
- ret = gst_camerabin_try_add_element (bin, new_elem);
-
- if (!ret) {
- gchar *elem_name = gst_element_get_name (new_elem);
- GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, (NULL),
- ("linking %s failed", elem_name));
- g_free (elem_name);
- }
-
- return ret;
-}
-
-/**
- * gst_camerabin_try_add_element:
- * @bin: tries adding an element to this bin
- * @new_elem: new element to be added
- *
- * Adds given element to given @bin. Looks for an unconnected src pad
- * from the @bin and links the element to it.
- *
- * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise.
- */
-gboolean
-gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem)
-{
- GstPad *bin_pad;
- GstElement *bin_elem;
- gboolean ret = TRUE;
-
- if (!bin || !new_elem) {
- return FALSE;
- }
-
- /* Get pads for linking */
- GST_DEBUG ("finding unconnected src pad");
- //bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC);
- bin_pad = gst_bin_find_unconnected_pad (bin, GST_PAD_SRC);
- GST_DEBUG ("unconnected pad %s:%s", GST_DEBUG_PAD_NAME (bin_pad));
- /* Add to bin */
- gst_bin_add (GST_BIN (bin), new_elem);
- /* Link, if unconnected pad was found, otherwise just add it to bin */
- if (bin_pad) {
- bin_elem = gst_pad_get_parent_element (bin_pad);
- gst_object_unref (bin_pad);
- if (!gst_element_link (bin_elem, new_elem)) {
- gst_bin_remove (bin, new_elem);
- ret = FALSE;
- }
- gst_object_unref (bin_elem);
- }
-
- return ret;
-}
-
-/**
- * gst_camerabin_create_and_add_element:
- * @bin: tries adding an element to this bin
- * @elem_name: name of the element to be created
- *
- * Creates an element according to given name and
- * adds it to given @bin. Looks for an unconnected src pad
- * from the @bin and links the element to it.
- *
- * Returns: pointer to the new element if successful, NULL otherwise.
- */
-GstElement *
-gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name)
-{
- GstElement *new_elem = NULL;
-
- GST_DEBUG ("adding %s", elem_name);
- new_elem = gst_element_factory_make (elem_name, NULL);
- if (!new_elem) {
- GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL),
- ("could not create \"%s\" element.", elem_name));
- } else if (!gst_camerabin_add_element (bin, new_elem)) {
- new_elem = NULL;
- }
-
- return new_elem;
-}
-
-/**
- * gst_camerabin_remove_elements_from_bin:
- * @bin: removes all elements from this bin
- *
- * Removes all elements from this @bin.
- */
-void
-gst_camerabin_remove_elements_from_bin (GstBin * bin)
-{
- GstIterator *iter = NULL;
- gpointer data = NULL;
- GstElement *elem = NULL;
- gboolean done = FALSE;
-
- iter = gst_bin_iterate_elements (bin);
- while (!done) {
- switch (gst_iterator_next (iter, &data)) {
- case GST_ITERATOR_OK:
- elem = GST_ELEMENT (data);
- gst_bin_remove (bin, elem);
- /* Iterator increased the element refcount, so unref */
- gst_object_unref (elem);
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- GST_WARNING_OBJECT (bin, "error in iterating elements");
- done = TRUE;
- break;
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
- }
- }
- gst_iterator_free (iter);
-}
-
-/**
- * gst_camerabin_drop_eos_probe:
- * @pad: pad receiving the event
- * @event: received event
- * @u_data: not used
- *
- * Event probe that drop all eos events.
- *
- * Returns: FALSE to drop the event, TRUE otherwise
- */
-gboolean
-gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data)
-{
- gboolean ret = TRUE;
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- GST_DEBUG ("dropping eos in %s:%s", GST_DEBUG_PAD_NAME (pad));
- ret = FALSE;
- break;
- default:
- break;
- }
- return ret;
-}
--- a/gst_plugins_good/gst/camerabin/camerabingeneral.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __CAMERABIN_GENERAL_H_
-#define __CAMERABIN_GENERAL_H_
-
-#include <sys/time.h>
-#include <time.h>
-
-#include <gst/gst.h>
-
-
-typedef struct timeval TIME_TYPE;
-#define GET_TIME(t) do { gettimeofday(&(t), NULL); } while(0)
-#define DIFF_TIME(t2,t1,d) do { d = ((t2).tv_sec - (t1).tv_sec) * 1000000 + \
- (t2).tv_usec - (t1).tv_usec; } while(0)
-
-#define _INIT_TIMER_BLOCK TIME_TYPE t1, t2; guint32 d; do {;}while (0)
-
-#define _OPEN_TIMER_BLOCK { GET_TIME(t1); do {;}while (0)
-#define _CLOSE_TIMER_BLOCK GET_TIME(t2); DIFF_TIME(t2,t1,d); \
- GST_DEBUG("elapsed time = %u\n", d); \
- } do {;}while (0)
-
-
-extern void
-camerabin_general_dbg_set_probe (GstElement * elem, gchar * pad_name,
- gboolean buf, gboolean evt);
-
-gboolean gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem);
-
-gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem);
-
-GstElement *gst_camerabin_create_and_add_element (GstBin * bin,
- const gchar * elem_name);
-
-void gst_camerabin_remove_elements_from_bin (GstBin * bin);
-
-gboolean
-gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data);
-
-GST_DEBUG_CATEGORY_EXTERN (gst_camerabin_debug);
-#define GST_CAT_DEFAULT gst_camerabin_debug
-
-#endif /* #ifndef __CAMERABIN_GENERAL_H_ */
--- a/gst_plugins_good/gst/camerabin/camerabinimage.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,571 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/**
- * SECTION:camerabinimage
- * @short_description: image capturing module of #GstCameraBin
- *
- * <refsect2>
- * <para>
- *
- * The pipeline for this module is:
- *
- * <informalexample>
- * <programlisting>
- *-----------------------------------------------------------------------------
- * (src0) -> queue ->
- * -> [post proc] -> tee <
- * (src1) -> imageenc -> metadatamuxer -> filesink
- *-----------------------------------------------------------------------------
- * </programlisting>
- * </informalexample>
- *
- * The property of elements are:
- *
- * queue - "max-size-buffers", 1, "leaky", 2,
- *
- * The image bin opens file for image writing in READY to PAUSED state change.
- * The image bin closes the file in PAUSED to READY state change.
- *
- * </para>
- * </refsect2>
- */
-
-/*
- * includes
- */
-
-#include <gst/gst.h>
-
-#include "camerabinimage.h"
-#include "camerabingeneral.h"
-
-#include "string.h"
-
-/* default internal element names */
-
-#define DEFAULT_SINK "filesink"
-#define DEFAULT_ENC "jpegenc"
-#define DEFAULT_META_MUX "metadatamux"
-
-enum
-{
- PROP_0,
- PROP_FILENAME
-};
-
-static gboolean gst_camerabin_image_create_elements (GstCameraBinImage * img);
-static void gst_camerabin_image_destroy_elements (GstCameraBinImage * img);
-
-static void gst_camerabin_image_dispose (GstCameraBinImage * sink);
-static GstStateChangeReturn
-gst_camerabin_image_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean gst_camerabin_image_send_event (GstElement * element,
- GstEvent * event);
-static void gst_camerabin_image_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_camerabin_image_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-GST_BOILERPLATE (GstCameraBinImage, gst_camerabin_image, GstBin, GST_TYPE_BIN);
-
-static const GstElementDetails gst_camerabin_image_details =
-GST_ELEMENT_DETAILS ("Image capture bin for camerabin",
- "Bin/Image",
- "Process and store image data",
- "Edgard Lima <edgard.lima@indt.org.br>\n"
- "Nokia Corporation <multimedia@maemo.org>");
-
-static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static void
-gst_camerabin_image_base_init (gpointer klass)
-{
- GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (eklass,
- gst_static_pad_template_get (&sink_template));
- gst_element_class_add_pad_template (eklass,
- gst_static_pad_template_get (&src_template));
- gst_element_class_set_details (eklass, &gst_camerabin_image_details);
-}
-
-static void
-gst_camerabin_image_class_init (GstCameraBinImageClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->dispose =
- (GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_camerabin_image_dispose);
- eklass->change_state = GST_DEBUG_FUNCPTR (gst_camerabin_image_change_state);
- eklass->send_event = GST_DEBUG_FUNCPTR (gst_camerabin_image_send_event);
-
- gobject_class->set_property =
- GST_DEBUG_FUNCPTR (gst_camerabin_image_set_property);
- gobject_class->get_property =
- GST_DEBUG_FUNCPTR (gst_camerabin_image_get_property);
-
- /**
- * GstCameraBinImage:filename
- *
- * This property can be used to specify the filename of the image.
- *
- **/
- g_object_class_install_property (gobject_class, PROP_FILENAME,
- g_param_spec_string ("filename", "Filename",
- "Filename of the image to save", NULL, G_PARAM_READWRITE));
-}
-
-static void
-gst_camerabin_image_init (GstCameraBinImage * img,
- GstCameraBinImageClass * g_class)
-{
- img->filename = g_string_new ("");
-
- img->pad_tee_enc = NULL;
- img->pad_tee_view = NULL;
-
- img->post = NULL;
- img->tee = NULL;
- img->enc = NULL;
- img->user_enc = NULL;
- img->meta_mux = NULL;
- img->sink = NULL;
- img->queue = NULL;
-
- /* Create src and sink ghost pads */
- img->sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
- gst_element_add_pad (GST_ELEMENT (img), img->sinkpad);
-
- img->srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
- gst_element_add_pad (GST_ELEMENT (img), img->srcpad);
-
- img->elements_created = FALSE;
-}
-
-static void
-gst_camerabin_image_dispose (GstCameraBinImage * img)
-{
- g_string_free (img->filename, TRUE);
- img->filename = NULL;
-
- if (img->user_enc) {
- gst_object_unref (img->user_enc);
- img->user_enc = NULL;
- }
-
- if (img->post) {
- gst_object_unref (img->post);
- img->post = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose ((GObject *) img);
-}
-
-static GstStateChangeReturn
-gst_camerabin_image_change_state (GstElement * element,
- GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstCameraBinImage *img = GST_CAMERABIN_IMAGE (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!gst_camerabin_image_create_elements (img)) {
- return GST_STATE_CHANGE_FAILURE;
- }
- /* Allow setting filename when image bin in READY state */
- gst_element_set_locked_state (img->sink, TRUE);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_element_set_locked_state (img->sink, FALSE);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- /* Set sink to NULL in order to write the file _now_ */
- GST_INFO ("write img file: %s", img->filename->str);
- gst_element_set_locked_state (img->sink, TRUE);
- gst_element_set_state (img->sink, GST_STATE_NULL);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_camerabin_image_destroy_elements (img);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-gboolean
-gst_camerabin_image_send_event (GstElement * element, GstEvent * event)
-{
- GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (element);
- gboolean ret = FALSE;
-
- GST_INFO ("got %s event", GST_EVENT_TYPE_NAME (event));
-
- if (GST_EVENT_IS_DOWNSTREAM (event)) {
- ret = gst_pad_send_event (bin->sinkpad, event);
- } else {
- if (bin->sink) {
- ret = gst_element_send_event (bin->sink, event);
- } else {
- GST_WARNING ("upstream event handling failed");
- }
- }
-
- return ret;
-}
-
-static void
-gst_camerabin_image_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (object);
-
- switch (prop_id) {
- case PROP_FILENAME:
- g_string_assign (bin->filename, g_value_get_string (value));
- if (bin->sink) {
- g_object_set (G_OBJECT (bin->sink), "location", bin->filename->str,
- NULL);
- } else {
- GST_INFO ("no sink, not setting name yet");
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_camerabin_image_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (object);
-
- switch (prop_id) {
- case PROP_FILENAME:
- g_value_set_string (value, bin->filename->str);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/*
- * static helper functions implementation
- */
-
-/**
- * metadata_write_probe:
- * @pad: sink pad of metadata muxer
- * @buffer: received buffer
- * @u_data: image bin object
- *
- * Buffer probe that sets Xmp.dc.type and Xmp.dc.format tags
- * to metadata muxer based on preceding element src pad caps.
- *
- * Returns: TRUE always
- */
-static gboolean
-metadata_write_probe (GstPad * pad, GstBuffer * buffer, gpointer u_data)
-{
- /* Add XMP tags */
- GstCameraBinImage *img = NULL;
- GstTagSetter *setter = NULL;
- GstPad *srcpad = NULL;
- GstCaps *caps = NULL;
- GstStructure *st = NULL;
-
- img = GST_CAMERABIN_IMAGE (u_data);
-
- g_return_val_if_fail (img != NULL, TRUE);
-
- setter = GST_TAG_SETTER (img->meta_mux);
-
- if (!setter) {
- GST_WARNING_OBJECT (img, "setting tags failed");
- goto done;
- }
-
- /* Xmp.dc.type tag */
- gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
- GST_TAG_CODEC, "Image", NULL);
- /* Xmp.dc.format tag */
- if (img->enc) {
- srcpad = gst_element_get_static_pad (img->enc, "src");
- }
- GST_LOG_OBJECT (img, "srcpad:%" GST_PTR_FORMAT, srcpad);
- if (srcpad) {
- caps = gst_pad_get_negotiated_caps (srcpad);
- GST_LOG_OBJECT (img, "caps:%" GST_PTR_FORMAT, caps);
- if (caps) {
- /* If there are many structures, we can't know which one to use */
- if (gst_caps_get_size (caps) != 1) {
- GST_WARNING_OBJECT (img, "can't decide structure for format tag");
- goto done;
- }
- st = gst_caps_get_structure (caps, 0);
- if (st) {
- GST_DEBUG_OBJECT (img, "Xmp.dc.format:%s", gst_structure_get_name (st));
- gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
- GST_TAG_VIDEO_CODEC, gst_structure_get_name (st), NULL);
- }
- }
- }
-done:
- if (caps)
- gst_caps_unref (caps);
- if (srcpad)
- gst_object_unref (srcpad);
-
- return TRUE;
-}
-
-
-/**
- * gst_camerabin_image_create_elements:
- * @img: a pointer to #GstCameraBinImage object
- *
- * This function creates needed #GstElements and resources to capture images.
- * Use gst_camerabin_image_destroy_elements to release these resources.
- *
- * Image bin:
- * img->sinkpad ! [ post process !] tee name=t0 ! encoder ! metadata ! filesink
- * t0. ! queue ! img->srcpad
- *
- * Returns: %TRUE if succeeded or FALSE if failed
- */
-static gboolean
-gst_camerabin_image_create_elements (GstCameraBinImage * img)
-{
- GstPad *sinkpad = NULL, *img_sinkpad = NULL, *img_srcpad = NULL;
- gboolean ret = FALSE;
- GstBin *imgbin = NULL;
-
- g_return_val_if_fail (img != NULL, FALSE);
-
- GST_DEBUG ("creating image capture elements");
-
- imgbin = GST_BIN (img);
-
- if (img->elements_created) {
- GST_WARNING ("elements already created");
- ret = TRUE;
- goto done;
- } else {
- img->elements_created = TRUE;
- }
-
- /* Create image pre/post-processing element if any */
- if (img->post) {
- if (!gst_camerabin_add_element (imgbin, img->post)) {
- goto done;
- }
- img_sinkpad = gst_element_get_static_pad (img->post, "sink");
- }
-
- /* Create tee */
- if (!(img->tee = gst_camerabin_create_and_add_element (imgbin, "tee"))) {
- goto done;
- }
-
- /* Set up sink ghost pad for img bin */
- if (!img_sinkpad) {
- img_sinkpad = gst_element_get_static_pad (img->tee, "sink");
- }
- gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad);
-
- /* Add colorspace converter */
- img->pad_tee_enc = gst_element_get_request_pad (img->tee, "src%d");
- if (!gst_camerabin_create_and_add_element (imgbin, "ffmpegcolorspace")) {
- goto done;
- }
-
- /* Create image encoder */
- if (img->user_enc) {
- img->enc = img->user_enc;
- if (!gst_camerabin_add_element (imgbin, img->enc)) {
- goto done;
- }
- } else if (!(img->enc =
- gst_camerabin_create_and_add_element (imgbin, DEFAULT_ENC))) {
- goto done;
- }
-
- /* Create metadata element */
- if (!(img->meta_mux =
- gst_camerabin_create_and_add_element (imgbin, DEFAULT_META_MUX))) {
- goto done;
- }
- /* Add probe for XMP metadata writing */
- sinkpad = gst_element_get_static_pad (img->meta_mux, "sink");
- gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (metadata_write_probe), img);
- gst_object_unref (sinkpad);
- /* Set "Intel" exif byte-order if possible */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (img->meta_mux),
- "exif-byte-order")) {
- g_object_set (G_OBJECT (img->meta_mux), "exif-byte-order", 1, NULL);
- }
-
- /* Create file sink element */
- if (!(img->sink =
- gst_camerabin_create_and_add_element (imgbin, DEFAULT_SINK))) {
- goto done;
- }
-
- /* Create queue element leading to view finder, attaches it to the tee */
- img->pad_tee_view = gst_element_get_request_pad (img->tee, "src%d");
- if (!(img->queue = gst_camerabin_create_and_add_element (imgbin, "queue"))) {
- goto done;
- }
-
- /* Set properties */
- g_object_set (G_OBJECT (img->sink), "location", img->filename->str, NULL);
- g_object_set (G_OBJECT (img->sink), "async", FALSE, NULL);
-
- g_object_set (G_OBJECT (img->queue), "max-size-buffers", 1, "leaky", 2, NULL);
-
- /* Set up src ghost pad for img bin */
- img_srcpad = gst_element_get_static_pad (img->queue, "src");
- gst_ghost_pad_set_target (GST_GHOST_PAD (img->srcpad), img_srcpad);
-
- /* Never let image bin eos events reach view finder */
- gst_pad_add_event_probe (img->srcpad,
- G_CALLBACK (gst_camerabin_drop_eos_probe), img);
-
- ret = TRUE;
-
-done:
-
- if (img_srcpad) {
- gst_object_unref (img_srcpad);
- }
- if (img_sinkpad) {
- gst_object_unref (img_sinkpad);
- }
- if (!ret) {
- gst_camerabin_image_destroy_elements (img);
- }
-
- return ret;
-}
-
-
-/**
- * gst_camerabin_image_destroy_elements:
- * @img: a pointer to #GstCameraBinImage object
- *
- * This function releases resources allocated in
- * gst_camerabin_image_create_elements.
- *
- */
-static void
-gst_camerabin_image_destroy_elements (GstCameraBinImage * img)
-{
- GST_LOG ("destroying img elements");
- if (img->pad_tee_enc) {
- gst_element_release_request_pad (img->tee, img->pad_tee_enc);
- img->pad_tee_enc = NULL;
- }
-
- if (img->pad_tee_view) {
- gst_element_release_request_pad (img->tee, img->pad_tee_view);
- img->pad_tee_view = NULL;
- }
-
- gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), NULL);
- gst_ghost_pad_set_target (GST_GHOST_PAD (img->srcpad), NULL);
-
- gst_camerabin_remove_elements_from_bin (GST_BIN (img));
-
- img->post = NULL;
- img->tee = NULL;
- img->enc = NULL;
- img->meta_mux = NULL;
- img->sink = NULL;
- img->queue = NULL;
-
- img->elements_created = FALSE;
-}
-
-void
-gst_camerabin_image_set_encoder (GstCameraBinImage * img, GstElement * encoder)
-{
- if (img->user_enc)
- gst_object_unref (img->user_enc);
- if (encoder)
- gst_object_ref (encoder);
-
- img->user_enc = encoder;
-}
-
-void
-gst_camerabin_image_set_postproc (GstCameraBinImage * img,
- GstElement * postproc)
-{
- if (img->post)
- gst_object_unref (img->post);
- if (postproc)
- gst_object_ref (postproc);
-
- img->post = postproc;
-}
-
-GstElement *
-gst_camerabin_image_get_encoder (GstCameraBinImage * img)
-{
- GstElement *enc;
-
- if (img->user_enc) {
- enc = img->user_enc;
- } else {
- enc = img->enc;
- }
-
- return enc;
-}
-
-GstElement *
-gst_camerabin_image_get_postproc (GstCameraBinImage * img)
-{
- return img->post;
-}
--- a/gst_plugins_good/gst/camerabin/camerabinimage.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __CAMERABIN_IMAGE_H__
-#define __CAMERABIN_IMAGE_H__
-
-#include <gst/gstbin.h>
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_CAMERABIN_IMAGE (gst_camerabin_image_get_type())
-#define GST_CAMERABIN_IMAGE_CAST(obj) ((GstCameraBinImage*)(obj))
-#define GST_CAMERABIN_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN_IMAGE,GstCameraBinImage))
-#define GST_CAMERABIN_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN_IMAGE,GstCameraBinImageClass))
-#define GST_IS_CAMERABIN_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN_IMAGE))
-#define GST_IS_CAMERABIN_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN_IMAGE))
-
-/**
- * GstCameraBinImage:
- *
- * The opaque #GstCameraBinImage structure.
- */
-
-typedef struct _GstCameraBinImage GstCameraBinImage;
-typedef struct _GstCameraBinImageClass GstCameraBinImageClass;
-
-struct _GstCameraBinImage
-{
- GstBin parent;
- GString *filename;
-
- /* Ghost pads of image bin */
- GstPad *sinkpad;
- GstPad *srcpad;
-
- /* Tee src pad leading to image encoder */
- GstPad *pad_tee_enc;
- /* Tee src pad leading to view finder */
- GstPad *pad_tee_view;
-
- GstElement *post;
-
- GstElement *tee;
- GstElement *enc;
- GstElement *user_enc;
- GstElement *meta_mux;
- GstElement *sink;
- GstElement *queue;
-
- gboolean elements_created;
-};
-
-struct _GstCameraBinImageClass
-{
- GstBinClass parent_class;
-};
-
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-GType gst_camerabin_image_get_type (void);
-
-void
-gst_camerabin_image_set_encoder (GstCameraBinImage * img, GstElement * encoder);
-
-void
-gst_camerabin_image_set_postproc (GstCameraBinImage * img,
- GstElement * postproc);
-
-GstElement *gst_camerabin_image_get_encoder (GstCameraBinImage * img);
-
-GstElement *gst_camerabin_image_get_postproc (GstCameraBinImage * img);
-
-G_END_DECLS
-
-#endif /* #ifndef __CAMERABIN_IMAGE_H__ */
--- a/gst_plugins_good/gst/camerabin/camerabinvideo.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,829 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/**
- * SECTION:camerabinvideo
- * @short_description: video recording module of #GstCameraBin
- *
- * <refsect2>
- * <para>
- *
- * The pipeline for this module is:
- *
- * <informalexample>
- * <programlisting>
- *-----------------------------------------------------------------------------
- * audiosrc -> audio_queue -> audioconvert -> volume -> audioenc
- * > videomux -> filesink
- * video_queue -> [timeoverlay] -> videoenc
- * -> [post proc] -> tee <
- * queue ->
- *-----------------------------------------------------------------------------
- * </programlisting>
- * </informalexample>
- *
- * The properties of elements are:
- *
- * queue - "leaky", 2 (Leaky on downstream (old buffers))
- *
- * </para>
- * </refsect2>
- */
-
-/*
- * includes
- */
-
-
-#include <gst/gst.h>
-#include "camerabingeneral.h"
-
-#include "camerabinvideo.h"
-
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-/*
- * defines and static global vars
- */
-
-/* internal element names */
-
-#define DEFAULT_AUD_SRC "pulsesrc"
-#define DEFAULT_AUD_ENC "vorbisenc"
-#define DEFAULT_VID_ENC "theoraenc"
-#define DEFAULT_MUX "oggmux"
-#define DEFAULT_SINK "filesink"
-
-#define USE_AUDIO_CONVERSION 1
-
-enum
-{
- PROP_0,
- PROP_FILENAME
-};
-
-static void gst_camerabin_video_dispose (GstCameraBinVideo * sink);
-static void gst_camerabin_video_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_camerabin_video_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static GstClock *gst_camerabin_video_provide_clock (GstElement * elem);
-static GstStateChangeReturn
-gst_camerabin_video_change_state (GstElement * element,
- GstStateChange transition);
-
-static
- gboolean camerabin_video_pad_tee_src0_have_buffer (GstPad * pad,
- GstBuffer * buffer, gpointer u_data);
-static gboolean camerabin_video_pad_aud_src_have_buffer (GstPad * pad,
- GstBuffer * buffer, gpointer u_data);
-static gboolean camerabin_video_sink_have_event (GstPad * pad, GstEvent * event,
- gpointer u_data);
-static gboolean gst_camerabin_video_create_elements (GstCameraBinVideo * vid);
-static void gst_camerabin_video_destroy_elements (GstCameraBinVideo * vid);
-
-GST_BOILERPLATE (GstCameraBinVideo, gst_camerabin_video, GstBin, GST_TYPE_BIN);
-
-static const GstElementDetails gst_camerabin_video_details =
-GST_ELEMENT_DETAILS ("Video capture bin for camerabin",
- "Bin/Video",
- "Process and store video data",
- "Edgard Lima <edgard.lima@indt.org.br>\n"
- "Nokia Corporation <multimedia@maemo.org>");
-
-static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-
-/* GObject methods implementation */
-
-static void
-gst_camerabin_video_base_init (gpointer klass)
-{
- GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (eklass,
- gst_static_pad_template_get (&sink_template));
- gst_element_class_add_pad_template (eklass,
- gst_static_pad_template_get (&src_template));
- gst_element_class_set_details (eklass, &gst_camerabin_video_details);
-}
-
-static void
-gst_camerabin_video_class_init (GstCameraBinVideoClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->dispose =
- (GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_camerabin_video_dispose);
- eklass->change_state = GST_DEBUG_FUNCPTR (gst_camerabin_video_change_state);
-
- eklass->provide_clock = GST_DEBUG_FUNCPTR (gst_camerabin_video_provide_clock);
-
- gobject_class->set_property =
- GST_DEBUG_FUNCPTR (gst_camerabin_video_set_property);
- gobject_class->get_property =
- GST_DEBUG_FUNCPTR (gst_camerabin_video_get_property);
-
- /**
- * GstCameraBinVideo:filename:
- *
- * This property can be used to specify the filename of the video.
- *
- **/
- g_object_class_install_property (gobject_class, PROP_FILENAME,
- g_param_spec_string ("filename", "Filename",
- "Filename of the video to save", NULL, G_PARAM_READWRITE));
-}
-
-static void
-gst_camerabin_video_init (GstCameraBinVideo * vid,
- GstCameraBinVideoClass * g_class)
-{
- vid->filename = g_string_new ("");
-
- vid->user_post = NULL;
- vid->user_vid_enc = NULL;
- vid->user_aud_enc = NULL;
- vid->user_aud_src = NULL;
- vid->user_mux = NULL;
-
- vid->aud_src = NULL;
- vid->sink = NULL;
- vid->tee = NULL;
- vid->volume = NULL;
- vid->video_queue = NULL;
-
- vid->tee_video_srcpad = NULL;
- vid->tee_vf_srcpad = NULL;
-
- vid->pending_eos = NULL;
-
- /* Create src and sink ghost pads */
- vid->sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
- gst_element_add_pad (GST_ELEMENT (vid), vid->sinkpad);
-
- vid->srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
- gst_element_add_pad (GST_ELEMENT (vid), vid->srcpad);
-
- /* Add probe for handling eos when stopping recording */
- gst_pad_add_event_probe (vid->sinkpad,
- G_CALLBACK (camerabin_video_sink_have_event), vid);
-}
-
-static void
-gst_camerabin_video_dispose (GstCameraBinVideo * vid)
-{
- GST_DEBUG_OBJECT (vid, "disposing");
-
- g_string_free (vid->filename, TRUE);
- vid->filename = NULL;
-
- if (vid->user_post) {
- gst_object_unref (vid->user_post);
- vid->user_post = NULL;
- }
-
- if (vid->user_vid_enc) {
- gst_object_unref (vid->user_vid_enc);
- vid->user_vid_enc = NULL;
- }
-
- if (vid->user_aud_enc) {
- gst_object_unref (vid->user_aud_enc);
- vid->user_aud_enc = NULL;
- }
-
- if (vid->user_aud_src) {
- gst_object_unref (vid->user_aud_src);
- vid->user_aud_src = NULL;
- }
-
- if (vid->user_mux) {
- gst_object_unref (vid->user_mux);
- vid->user_mux = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose ((GObject *) vid);
-}
-
-
-static void
-gst_camerabin_video_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstCameraBinVideo *bin = GST_CAMERABIN_VIDEO (object);
-
- switch (prop_id) {
- case PROP_FILENAME:
- g_string_assign (bin->filename, g_value_get_string (value));
- if (bin->sink) {
- g_object_set (G_OBJECT (bin->sink), "location", bin->filename->str,
- NULL);
- } else {
- GST_INFO ("no sink, not setting name yet");
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_camerabin_video_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstCameraBinVideo *bin = GST_CAMERABIN_VIDEO (object);
-
- switch (prop_id) {
- case PROP_FILENAME:
- g_value_set_string (value, bin->filename->str);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/* GstElement methods implementation */
-
-static GstClock *
-gst_camerabin_video_provide_clock (GstElement * elem)
-{
- GstElement *aud_src = GST_CAMERABIN_VIDEO (elem)->aud_src;
- if (aud_src) {
- return gst_element_provide_clock (aud_src);
- } else {
- return NULL;
- }
-}
-
-static GstStateChangeReturn
-gst_camerabin_video_change_state (GstElement * element,
- GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstCameraBinVideo *vid = GST_CAMERABIN_VIDEO (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!gst_camerabin_video_create_elements (vid)) {
- return GST_STATE_CHANGE_FAILURE;
- }
- /* Don't change sink to READY yet to allow changing the
- filename in READY state. */
- gst_element_set_locked_state (vid->sink, TRUE);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- vid->calculate_adjust_ts_video = TRUE;
- vid->calculate_adjust_ts_aud = TRUE;
- g_object_set (G_OBJECT (vid->sink), "async", FALSE, NULL);
- gst_element_set_locked_state (vid->sink, FALSE);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- vid->calculate_adjust_ts_video = TRUE;
- vid->calculate_adjust_ts_aud = TRUE;
- break;
-
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- /* Set sink to NULL in order to write the file _now_ */
- GST_INFO ("write vid file: %s", vid->filename->str);
- gst_element_set_locked_state (vid->sink, TRUE);
- gst_element_set_state (vid->sink, GST_STATE_NULL);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- if (vid->pending_eos) {
- /* Video bin is still paused, so push eos directly to video queue */
- GST_DEBUG_OBJECT (vid, "pushing pending eos");
- gst_pad_push_event (vid->tee_video_srcpad, vid->pending_eos);
- vid->pending_eos = NULL;
- }
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- /* Reset counters related to timestamp rewriting */
- vid->adjust_ts_video = 0;
- vid->last_ts_video = 0;
- vid->adjust_ts_aud = 0;
- vid->last_ts_aud = 0;
-
- if (vid->pending_eos) {
- gst_event_unref (vid->pending_eos);
- vid->pending_eos = NULL;
- }
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_camerabin_video_destroy_elements (vid);
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-/*
- * static helper functions implementation
- */
-
-/**
- * camerabin_video_pad_tee_src0_have_buffer:
- * @pad: tee src pad leading to video encoding
- * @event: received buffer
- * @u_data: video bin object
- *
- * Buffer probe for rewriting video buffer timestamps.
- *
- * Returns: TRUE always
- */
-static gboolean
-camerabin_video_pad_tee_src0_have_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data)
-{
- GstCameraBinVideo *vid = (GstCameraBinVideo *) u_data;
-
- GST_LOG ("buffer in with size %d ts %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-
- if (G_UNLIKELY (vid->calculate_adjust_ts_video)) {
- GstEvent *event;
- GstObject *tee;
- GstPad *sinkpad;
- vid->adjust_ts_video = GST_BUFFER_TIMESTAMP (buffer) - vid->last_ts_video;
- vid->calculate_adjust_ts_video = FALSE;
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
- 0, GST_CLOCK_TIME_NONE, vid->last_ts_video);
- /* Send the newsegment to both view finder and video bin */
- tee = gst_pad_get_parent (pad);
- sinkpad = gst_element_get_static_pad (GST_ELEMENT (tee), "sink");
- gst_pad_send_event (sinkpad, event);
- gst_object_unref (tee);
- gst_object_unref (sinkpad);
- GST_LOG_OBJECT (vid, "vid ts adjustment: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (vid->adjust_ts_video));
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- }
- GST_BUFFER_TIMESTAMP (buffer) -= vid->adjust_ts_video;
- vid->last_ts_video = GST_BUFFER_TIMESTAMP (buffer);
- if (GST_BUFFER_DURATION_IS_VALID (buffer))
- vid->last_ts_video += GST_BUFFER_DURATION (buffer);
-
-
- GST_LOG ("buffer out with size %d ts %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- return TRUE;
-}
-
-/**
- * camerabin_video_pad_aud_src_have_buffer:
- * @pad: audio source src pad
- * @event: received buffer
- * @u_data: video bin object
- *
- * Buffer probe for rewriting audio buffer timestamps.
- *
- * Returns: TRUE always
- */
-static gboolean
-camerabin_video_pad_aud_src_have_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data)
-{
- GstCameraBinVideo *vid = (GstCameraBinVideo *) u_data;
-
- if (vid->calculate_adjust_ts_aud) {
- GstEvent *event;
- GstPad *peerpad = NULL;
- vid->adjust_ts_aud = GST_BUFFER_TIMESTAMP (buffer) - vid->last_ts_aud;
- vid->calculate_adjust_ts_aud = FALSE;
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
- 0, GST_CLOCK_TIME_NONE, vid->last_ts_aud);
- peerpad = gst_pad_get_peer (pad);
- if (peerpad) {
- gst_pad_send_event (peerpad, event);
- gst_object_unref (peerpad);
- }
- GST_LOG_OBJECT (vid, "aud ts adjustment: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (vid->adjust_ts_aud));
- GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
- }
- GST_BUFFER_TIMESTAMP (buffer) -= vid->adjust_ts_aud;
- vid->last_ts_aud = GST_BUFFER_TIMESTAMP (buffer);
- if (GST_BUFFER_DURATION_IS_VALID (buffer))
- vid->last_ts_aud += GST_BUFFER_DURATION (buffer);
- GST_LOG ("buffer out with size %d ts %" GST_TIME_FORMAT,
- GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
- return TRUE;
-}
-
-/**
- * camerabin_video_sink_have_event:
- * @pad: video bin sink pad
- * @event: received event
- * @u_data: video bin object
- *
- * Event probe for video bin eos handling.
- * Copies the eos event to audio branch of video bin.
- *
- * Returns: FALSE to drop the event, TRUE otherwise
- */
-static gboolean
-camerabin_video_sink_have_event (GstPad * pad, GstEvent * event,
- gpointer u_data)
-{
- GstCameraBinVideo *vid = (GstCameraBinVideo *) u_data;
- gboolean ret = TRUE;
-
- GST_DEBUG_OBJECT (vid, "got videobin sink event: %s",
- GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- if (vid->aud_src) {
- GST_DEBUG_OBJECT (vid, "copying %s to audio branch",
- GST_EVENT_TYPE_NAME (event));
- gst_element_send_event (vid->aud_src, gst_event_copy (event));
- }
-
- /* If we're paused, we can't pass eos to video now to avoid blocking.
- Instead send eos when changing to playing next time. */
- if (GST_STATE (GST_ELEMENT (vid)) == GST_STATE_PAUSED) {
- GST_DEBUG_OBJECT (vid, "paused, delay eos sending");
- vid->pending_eos = gst_event_ref (event);
- ret = FALSE; /* Drop the event */
- }
- break;
- default:
- break;
- }
- return ret;
-}
-
-/**
- * gst_camerabin_video_create_elements:
- * @vid: a pointer to #GstCameraBinVideo
- *
- * This function creates the needed #GstElements and resources to record videos.
- * Use gst_camerabin_video_destroy_elements() to free these resources.
- *
- * Returns: %TRUE if succeeded or FALSE if failed
- */
-static gboolean
-gst_camerabin_video_create_elements (GstCameraBinVideo * vid)
-{
- GstPad *pad = NULL, *vid_sinkpad = NULL, *vid_srcpad = NULL;
- GstBin *vidbin = GST_BIN (vid);
- GstElement *queue = NULL;
-
- vid->adjust_ts_video = 0;
- vid->last_ts_video = 0;
- vid->calculate_adjust_ts_video = FALSE;
-
- vid->adjust_ts_aud = 0;
- vid->last_ts_aud = 0;
- vid->calculate_adjust_ts_aud = FALSE;
-
- /* Add video post processing element if any */
- if (vid->user_post) {
- if (!gst_camerabin_add_element (vidbin, vid->user_post)) {
- goto error;
- }
- vid_sinkpad = gst_element_get_static_pad (vid->user_post, "sink");
- }
-
- /* Add tee element */
- if (!(vid->tee = gst_camerabin_create_and_add_element (vidbin, "tee"))) {
- goto error;
- }
-
- /* Set up sink ghost pad for video bin */
- if (!vid_sinkpad) {
- vid_sinkpad = gst_element_get_static_pad (vid->tee, "sink");
- }
- gst_ghost_pad_set_target (GST_GHOST_PAD (vid->sinkpad), vid_sinkpad);
-
-
- /* Add queue element for video */
- vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d");
- if (!(vid->video_queue =
- gst_camerabin_create_and_add_element (vidbin, "queue"))) {
- goto error;
- }
-
- /* Add probe for rewriting video timestamps */
- gst_pad_add_buffer_probe (vid->tee_video_srcpad,
- G_CALLBACK (camerabin_video_pad_tee_src0_have_buffer), vid);
-
-
-#ifdef USE_TIMEOVERLAY
- /* Add timeoverlay element to visualize elapsed time for debugging */
- if (!(gst_camerabin_create_and_add_element (vidbin, "timeoverlay"))) {
- goto error;
- }
-#endif
-
- /* Add user set or default video encoder element */
- if (vid->user_vid_enc) {
- vid->vid_enc = vid->user_vid_enc;
- if (!gst_camerabin_add_element (vidbin, vid->vid_enc)) {
- goto error;
- }
- } else if (!(vid->vid_enc =
- gst_camerabin_create_and_add_element (vidbin, DEFAULT_VID_ENC))) {
- goto error;
- }
-
- /* Add user set or default muxer element */
- if (vid->user_mux) {
- vid->muxer = vid->user_mux;
- if (!gst_camerabin_add_element (vidbin, vid->muxer)) {
- goto error;
- }
- } else if (!(vid->muxer =
- gst_camerabin_create_and_add_element (vidbin, DEFAULT_MUX))) {
- goto error;
- }
-
- /* Add sink element for storing the video */
- if (!(vid->sink =
- gst_camerabin_create_and_add_element (vidbin, DEFAULT_SINK))) {
- goto error;
- }
- g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, NULL);
-
-
- /* Add user set or default audio source element */
- if (vid->user_aud_src) {
- vid->aud_src = vid->user_aud_src;
- if (!gst_camerabin_add_element (vidbin, vid->aud_src)) {
- goto error;
- }
- } else if (!(vid->aud_src =
- gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_SRC))) {
- goto error;
- }
-
- /* Add queue element for audio */
- if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) {
- goto error;
- }
- queue = NULL;
-
- /* Add optional audio conversion and volume elements and
- raise no errors if adding them fails */
-#ifdef USE_AUDIO_CONVERSION
- if (!gst_camerabin_try_add_element (vidbin,
- gst_element_factory_make ("audioconvert", NULL))) {
- GST_WARNING_OBJECT (vid, "unable to add audio conversion element");
- /* gst_camerabin_try_add_element() destroyed the element */
- }
-#endif
- vid->volume = gst_element_factory_make ("volume", NULL);
- if (!gst_camerabin_try_add_element (vidbin, vid->volume)) {
- GST_WARNING_OBJECT (vid, "unable to add volume element");
- /* gst_camerabin_try_add_element() destroyed the element */
- vid->volume = NULL;
- }
-
- /* Add user set or default audio encoder element */
- if (vid->user_aud_enc) {
- vid->aud_enc = vid->user_aud_enc;
- if (!gst_camerabin_add_element (vidbin, vid->aud_enc)) {
- goto error;
- }
- } else if (!(vid->aud_enc =
- gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC))) {
- goto error;
- }
-
- /* Link audio part to the muxer */
- if (!gst_element_link (vid->aud_enc, vid->muxer)) {
- GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL),
- ("linking audio encoder and muxer failed"));
- goto error;
- }
-
- /* Add queue leading out of the video bin and to view finder */
- vid->tee_vf_srcpad = gst_element_get_request_pad (vid->tee, "src%d");
- if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) {
- goto error;
- }
- /* Set queue leaky, we don't want to block video encoder feed, but
- prefer leaking view finder buffers instead. */
- g_object_set (G_OBJECT (queue), "leaky", 2, NULL);
-
- /* Set up src ghost pad for video bin */
- vid_srcpad = gst_element_get_static_pad (queue, "src");
- gst_ghost_pad_set_target (GST_GHOST_PAD (vid->srcpad), vid_srcpad);
- /* Never let video bin eos events reach view finder */
- gst_pad_add_event_probe (vid_srcpad,
- G_CALLBACK (gst_camerabin_drop_eos_probe), vid);
-
- pad = gst_element_get_static_pad (vid->aud_src, "src");
- gst_pad_add_buffer_probe (pad,
- G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid);
- gst_object_unref (pad);
-
- GST_DEBUG ("created video elements");
-
- return TRUE;
-
-error:
-
- gst_camerabin_video_destroy_elements (vid);
-
- return FALSE;
-
-}
-
-/**
- * gst_camerabin_video_destroy_elements:
- * @vid: a pointer to #GstCameraBinVideo
- *
- * This function destroys all the elements created by
- * gst_camerabin_video_create_elements().
- *
- */
-static void
-gst_camerabin_video_destroy_elements (GstCameraBinVideo * vid)
-{
- GST_DEBUG ("destroying video elements");
-
- /* Release tee request pads */
- if (vid->tee_video_srcpad) {
- gst_element_release_request_pad (vid->tee, vid->tee_video_srcpad);
- vid->tee_video_srcpad = NULL;
- }
- if (vid->tee_vf_srcpad) {
- gst_element_release_request_pad (vid->tee, vid->tee_vf_srcpad);
- vid->tee_vf_srcpad = NULL;
- }
-
- gst_ghost_pad_set_target (GST_GHOST_PAD (vid->sinkpad), NULL);
- gst_ghost_pad_set_target (GST_GHOST_PAD (vid->srcpad), NULL);
-
- gst_camerabin_remove_elements_from_bin (GST_BIN (vid));
-
- vid->aud_src = NULL;
- vid->sink = NULL;
- vid->tee = NULL;
- vid->volume = NULL;
- vid->video_queue = NULL;
- vid->vid_enc = NULL;
- vid->aud_enc = NULL;
- vid->muxer = NULL;
-
- if (vid->pending_eos) {
- gst_event_unref (vid->pending_eos);
- vid->pending_eos = NULL;
- }
-
- return;
-}
-
-/*
- * Set & get mute and video capture elements
- */
-
-void
-gst_camerabin_video_set_mute (GstCameraBinVideo * vid, gboolean mute)
-{
- if (vid && vid->volume) {
- GST_DEBUG_OBJECT (vid, "setting mute %s", mute ? "on" : "off");
- g_object_set (vid->volume, "mute", mute, NULL);
- }
-}
-
-void
-gst_camerabin_video_set_post (GstCameraBinVideo * vid, GstElement * post)
-{
- GstElement **user_post;
- GST_DEBUG_OBJECT (vid, "setting video post processing: %" GST_PTR_FORMAT,
- post);
- GST_OBJECT_LOCK (vid);
- user_post = &vid->user_post;
- gst_object_replace ((GstObject **) user_post, GST_OBJECT (post));
- GST_OBJECT_UNLOCK (vid);
-}
-
-void
-gst_camerabin_video_set_video_enc (GstCameraBinVideo * vid,
- GstElement * video_enc)
-{
- GstElement **user_vid_enc;
- GST_DEBUG_OBJECT (vid, "setting video encoder: %" GST_PTR_FORMAT, video_enc);
- GST_OBJECT_LOCK (vid);
- user_vid_enc = &vid->user_vid_enc;
- gst_object_replace ((GstObject **) user_vid_enc, GST_OBJECT (video_enc));
- GST_OBJECT_UNLOCK (vid);
-}
-
-void
-gst_camerabin_video_set_audio_enc (GstCameraBinVideo * vid,
- GstElement * audio_enc)
-{
- GstElement **user_aud_enc;
- GST_DEBUG_OBJECT (vid, "setting audio encoder: %" GST_PTR_FORMAT, audio_enc);
- GST_OBJECT_LOCK (vid);
- user_aud_enc = &vid->user_aud_enc;
- gst_object_replace ((GstObject **) user_aud_enc, GST_OBJECT (audio_enc));
- GST_OBJECT_UNLOCK (vid);
-}
-
-void
-gst_camerabin_video_set_muxer (GstCameraBinVideo * vid, GstElement * muxer)
-{
- GstElement **user_mux;
- GST_DEBUG_OBJECT (vid, "setting muxer: %" GST_PTR_FORMAT, muxer);
- GST_OBJECT_LOCK (vid);
- user_mux = &vid->user_mux;
- gst_object_replace ((GstObject **) user_mux, GST_OBJECT (muxer));
- GST_OBJECT_UNLOCK (vid);
-}
-
-void
-gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
- GstElement * audio_src)
-{
- GstElement **user_aud_src;
- GST_DEBUG_OBJECT (vid, "setting audio source: %" GST_PTR_FORMAT, audio_src);
- GST_OBJECT_LOCK (vid);
- user_aud_src = &vid->user_aud_src;
- gst_object_replace ((GstObject **) user_aud_src, GST_OBJECT (audio_src));
- GST_OBJECT_UNLOCK (vid);
-}
-
-gboolean
-gst_camerabin_video_get_mute (GstCameraBinVideo * vid)
-{
- gboolean mute = ARG_DEFAULT_MUTE;
-
- if (vid && vid->volume) {
- g_object_get (vid->volume, "mute", &mute, NULL);
- }
- return mute;
-}
-
-GstElement *
-gst_camerabin_video_get_post (GstCameraBinVideo * vid)
-{
- return vid->user_post;
-}
-
-GstElement *
-gst_camerabin_video_get_video_enc (GstCameraBinVideo * vid)
-{
- return vid->vid_enc ? vid->vid_enc : vid->user_vid_enc;
-}
-
-GstElement *
-gst_camerabin_video_get_audio_enc (GstCameraBinVideo * vid)
-{
- return vid->aud_enc ? vid->aud_enc : vid->user_aud_enc;
-}
-
-GstElement *
-gst_camerabin_video_get_muxer (GstCameraBinVideo * vid)
-{
- return vid->muxer ? vid->muxer : vid->user_mux;
-}
-
-GstElement *
-gst_camerabin_video_get_audio_src (GstCameraBinVideo * vid)
-{
- return vid->aud_src ? vid->aud_src : vid->user_aud_src;
-}
--- a/gst_plugins_good/gst/camerabin/camerabinvideo.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __CAMERABIN_VIDEO_H__
-#define __CAMERABIN_VIDEO_H__
-
-#include <gst/gstbin.h>
-
-G_BEGIN_DECLS
-
-//#define USE_TIMEOVERLAY 1
-
-#define ARG_DEFAULT_MUTE FALSE
-
-#define GST_TYPE_CAMERABIN_VIDEO (gst_camerabin_video_get_type())
-#define GST_CAMERABIN_VIDEO_CAST(obj) ((GstCameraBinVideo*)(obj))
-#define GST_CAMERABIN_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN_VIDEO,GstCameraBinVideo))
-#define GST_CAMERABIN_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN_VIDEO,GstCameraBinVideoClass))
-#define GST_IS_CAMERABIN_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN_VIDEO))
-#define GST_IS_CAMERABIN_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN_VIDEO))
-
-/**
- * GstCameraBinVideo:
- *
- * The opaque #GstCameraBinVideo structure.
- */
-
-typedef struct _GstCameraBinVideo GstCameraBinVideo;
-typedef struct _GstCameraBinVideoClass GstCameraBinVideoClass;
-
-struct _GstCameraBinVideo
-{
- GstBin parent;
-
- GString *filename;
-
- /* A/V timestamp rewriting */
- guint64 adjust_ts_video;
- guint64 last_ts_video;
- gboolean calculate_adjust_ts_video;
-
- guint64 adjust_ts_aud;
- guint64 last_ts_aud;
- gboolean calculate_adjust_ts_aud;
-
- /* Sink and src pads of video bin */
- GstPad *sinkpad;
- GstPad *srcpad;
-
- /* Tee src pads leading to video encoder and view finder */
- GstPad *tee_video_srcpad;
- GstPad *tee_vf_srcpad;
-
- /* User set elements */
- GstElement *user_post; /* Video post processing */
- GstElement *user_vid_enc;
- GstElement *user_aud_enc;
- GstElement *user_aud_src;
- GstElement *user_mux;
-
- /* Other elements */
- GstElement *aud_src; /* Audio source */
- GstElement *sink; /* Sink for recorded video */
- GstElement *tee; /* Split output to view finder and recording sink */
- GstElement *volume; /* Volume for muting */
- GstElement *video_queue; /* Buffer for raw video frames */
- GstElement *vid_enc; /* Video encoder */
- GstElement *aud_enc; /* Audio encoder */
- GstElement *muxer; /* Muxer */
-
- GstEvent *pending_eos;
-};
-
-struct _GstCameraBinVideoClass
-{
- GstBinClass parent_class;
-};
-
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-GType gst_camerabin_video_get_type (void);
-
-/*
- * external function prototypes
- */
-
-void gst_camerabin_video_set_mute (GstCameraBinVideo * vid, gboolean mute);
-
-void gst_camerabin_video_set_post (GstCameraBinVideo * vid, GstElement * post);
-
-void
-gst_camerabin_video_set_video_enc (GstCameraBinVideo * vid,
- GstElement * video_enc);
-
-void
-gst_camerabin_video_set_audio_enc (GstCameraBinVideo * vid,
- GstElement * audio_enc);
-
-void
-gst_camerabin_video_set_muxer (GstCameraBinVideo * vid, GstElement * muxer);
-
-void
-gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
- GstElement * audio_src);
-
-
-gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid);
-
-GstElement *gst_camerabin_video_get_post (GstCameraBinVideo * vid);
-
-GstElement *gst_camerabin_video_get_video_enc (GstCameraBinVideo * vid);
-
-GstElement *gst_camerabin_video_get_audio_enc (GstCameraBinVideo * vid);
-
-GstElement *gst_camerabin_video_get_muxer (GstCameraBinVideo * vid);
-
-GstElement *gst_camerabin_video_get_audio_src (GstCameraBinVideo * vid);
-
-G_END_DECLS
-
-#endif /* #ifndef __CAMERABIN_VIDEO_H__ */
--- a/gst_plugins_good/gst/camerabin/gstcamerabin-marshal.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-
-#include <glib-object.h>
-
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v) g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v) g_value_get_int (v)
-#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
-#define g_marshal_value_peek_long(v) g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
-#define g_marshal_value_peek_float(v) g_value_get_float (v)
-#define g_marshal_value_peek_double(v) g_value_get_double (v)
-#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v) g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v) g_value_get_object (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- * Do not access GValues directly in your code. Instead, use the
- * g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
-#define g_marshal_value_peek_char(v) (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v) (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v) (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
-#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
-#define g_marshal_value_peek_float(v) (v)->data[0].v_float
-#define g_marshal_value_peek_double(v) (v)->data[0].v_double
-#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* VOID:INT,INT,INT,INT (gstcamerabin-marshal.list:4) */
-void
-gst_camerabin_marshal_VOID__INT_INT_INT_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__INT_INT_INT_INT) (gpointer data1,
- gint arg_1,
- gint arg_2,
- gint arg_3,
- gint arg_4,
- gpointer data2);
- register GMarshalFunc_VOID__INT_INT_INT_INT callback;
- register GCClosure *cc = (GCClosure*) closure;
- register gpointer data1, data2;
-
- g_return_if_fail (n_param_values == 5);
-
- if (G_CCLOSURE_SWAP_DATA (closure))
- {
- data1 = closure->data;
- data2 = g_value_peek_pointer (param_values + 0);
- }
- else
- {
- data1 = g_value_peek_pointer (param_values + 0);
- data2 = closure->data;
- }
- callback = (GMarshalFunc_VOID__INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
-
- callback (data1,
- g_marshal_value_peek_int (param_values + 1),
- g_marshal_value_peek_int (param_values + 2),
- g_marshal_value_peek_int (param_values + 3),
- g_marshal_value_peek_int (param_values + 4),
- data2);
-}
-
-/* VOID:INT,INT (gstcamerabin-marshal.list:5) */
-void
-gst_camerabin_marshal_VOID__INT_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer data1,
- gint arg_1,
- gint arg_2,
- gpointer data2);
- register GMarshalFunc_VOID__INT_INT callback;
- register GCClosure *cc = (GCClosure*) closure;
- register gpointer data1, data2;
-
- g_return_if_fail (n_param_values == 3);
-
- if (G_CCLOSURE_SWAP_DATA (closure))
- {
- data1 = closure->data;
- data2 = g_value_peek_pointer (param_values + 0);
- }
- else
- {
- data1 = g_value_peek_pointer (param_values + 0);
- data2 = closure->data;
- }
- callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
-
- callback (data1,
- g_marshal_value_peek_int (param_values + 1),
- g_marshal_value_peek_int (param_values + 2),
- data2);
-}
-
--- a/gst_plugins_good/gst/camerabin/gstcamerabin-marshal.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-
-#ifndef __gst_camerabin_MARSHAL_H__
-#define __gst_camerabin_MARSHAL_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* VOID:INT,INT,INT,INT (gstcamerabin-marshal.list:4) */
-extern void gst_camerabin_marshal_VOID__INT_INT_INT_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-/* VOID:INT,INT (gstcamerabin-marshal.list:5) */
-extern void gst_camerabin_marshal_VOID__INT_INT (GClosure *closure,
- GValue *return_value,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint,
- gpointer marshal_data);
-
-G_END_DECLS
-
-#endif /* __gst_camerabin_MARSHAL_H__ */
-
--- a/gst_plugins_good/gst/camerabin/gstcamerabin.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2769 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/**
- * SECTION:gstcamerabin
- * @short_description: camera capture bin
- *
- * <refsect2>
- * <para>
- * GstCameraBin is a high-level camera object that encapsulates the gstreamer
- * internals and provides a task based API for the application. It consists of
- * three main data paths: view-finder, image capture and video capture.
- * </para>
- * <informalfigure>
- * <mediaobject>
- * <imageobject><imagedata fileref="camerabin.png"/></imageobject>
- * <textobject><phrase>CameraBin structure</phrase></textobject>
- * <caption><para>Structural decomposition of CameraBin object.</para></caption>
- * </mediaobject>
- * </informalfigure>
- * </refsect2>
- * <refsect2>
- * <title>Example launch line</title>
- * <para>
- * <programlisting>
- * gst-launch -v -m camerabin filename=test.jpeg
- * </programlisting>
- * </para>
- * </refsect2>
- * <refsect2>
- * <title>Image capture</title>
- * <para>
- * Taking still images is initiated with the #GstCameraBin::user-start action
- * signal. Once the image has captured, #GstCameraBin::img-done signal is fired.
- * It allows to decide wheter to take another picture (burst capture, bracketing
- * shot) or stop capturing. The last captured image is shown
- * until one switches back to view finder using #GstCameraBin::user-stop action
- * signal.
- * </para>
- * <para>
- * Available resolutions can be taken from the #GstCameraBin:inputcaps property.
- * Image capture resolution can be set with #GstCameraBin::user-image-res
- * action signal.
- * </para>
- * </refsect2>
- * <refsect2>
- * <title>Video capture</title>
- * <para>
- * Video capture is started with the #GstCameraBin::user-start action signal too.
- * In addition to image capture one can use #GstCameraBin::user-pause to
- * pause recording and #GstCameraBin::user-stop to end recording.
- * </para>
- * <para>
- * Available resolutions and fps can be taken from the #GstCameraBin:inputcaps
- * property. #GstCameraBin::user-res-fps action signal can be used to set frame
- * rate and resolution for the video recording and view finder as well.
- * </para>
- * </refsect2>
- * <refsect2>
- * <title>Photography interface</title>
- * <para>
- * GstCameraBin implements gst photography interface, which can be used to set
- * and get different settings related to digital imaging. Since currently many
- * of these settings require low-level support the photography interface support
- * is dependent on video src element. In practice photography interface settings
- * cannot be used successfully until in PAUSED state when the video src has
- * opened the video device.
- * </para>
- * </refsect2>
- * <refsect2>
- * <title>States</title>
- * <para>
- * Elements within GstCameraBin are created and destroyed when switching
- * between NULL and READY states. Therefore element properties should be set
- * in NULL state. User set elements are not unreffed until GstCameraBin is
- * unreffed or replaced by a new user set element. Initially only elements needed
- * for view finder mode are created to speed up startup. Image bin and video bin
- * elements are created when setting the mode or starting capture.
- * </para>
- * </refsect2>
- * <refsect2>
- * <note>
- * <para>
- * Since the muxers tested so far have problems with discontinous buffers, QoS
- * has been disabled, and then in order to record video, you MUST ensure that
- * there is enough CPU to encode the video. Thus choose smart resolution and
- * frames per second values. It is also highly recommended to avoid color
- * conversions; make sure all the elements involved work with the same colorspace
- * (i.e. rgb or yuv i420 or whatelse).
- * </para>
- * </note>
- * </refsect2>
- */
-
-/*
- * The pipeline in the camerabin is
- *
- * "image bin"
- * videosrc ! crop ! scale ! out-sel <------> in-sel ! scale ! ffmpegcsp ! vfsink
- * "video bin"
- *
- * it is possible to have 'ffmpegcolorspace' and 'capsfilter' just after
- * v4l2camsrc
- *
- * The properties of elements are:
- *
- * vfsink - "sync", FALSE, "qos", FALSE
- * output-selector - "resend-latest", FALSE
- * input-selector - "select-all", TRUE
- */
-
-/*
- * includes
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <string.h>
-#include <stdlib.h>
-
-#include <gst/gst.h>
-/* FIXME: include #include <gst/gst-i18n-plugin.h> and use _(" ") */
-
-#ifndef __SYMBIAN32__
-#include <gst/gst-i18n-plugin.h>
-#else
-#include <gst/gst-i18n-plugin.h>
-#endif
-
-#ifdef __SYMBIAN32__
-#include <gst/gstinfo.h>
-#endif
-
-
-
-
-#include "gstcamerabin.h"
-#include "gstcamerabinxoverlay.h"
-#include "gstcamerabincolorbalance.h"
-#include "gstcamerabinphotography.h"
-
-#include "camerabingeneral.h"
-
-#include "gstcamerabin-marshal.h"
-
-#ifdef __SYMBIAN32__
-#include <glib_global.h>
-#endif
-/*
- * enum and types
- */
-
-enum
-{
- /* action signals */
- USER_START_SIGNAL,
- USER_STOP_SIGNAL,
- USER_PAUSE_SIGNAL,
- USER_RES_FPS_SIGNAL,
- USER_IMAGE_RES_SIGNAL,
- /* emit signals */
- IMG_DONE_SIGNAL,
- LAST_SIGNAL
-};
-
-enum
-{
- ARG_0,
- ARG_FILENAME,
- ARG_MODE,
- ARG_MUTE,
- ARG_ZOOM,
- ARG_IMAGE_POST,
- ARG_IMAGE_ENC,
- ARG_VIDEO_POST,
- ARG_VIDEO_ENC,
- ARG_AUDIO_ENC,
- ARG_VIDEO_MUX,
- ARG_VF_SINK,
- ARG_VIDEO_SRC,
- ARG_AUDIO_SRC,
- ARG_INPUT_CAPS,
- ARG_FILTER_CAPS
-};
-
-/*
- * defines and static global vars
- */
-
-static guint camerabin_signals[LAST_SIGNAL];
-
-#define GST_TYPE_CAMERABIN_MODE (gst_camerabin_mode_get_type ())
-
-/* default and range values for args */
-
-#define DEFAULT_MODE MODE_IMAGE
-#define DEFAULT_ZOOM 100
-#define DEFAULT_WIDTH 640
-#define DEFAULT_HEIGHT 480
-#define DEFAULT_CAPTURE_WIDTH 800
-#define DEFAULT_CAPTURE_HEIGHT 600
-#define DEFAULT_FPS_N 0 /* makes it use the default */
-#define DEFAULT_FPS_D 1
-#define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420"
-/* Using "bilinear" as default zoom method */
-#define CAMERABIN_DEFAULT_ZOOM_METHOD 1
-
-#define MIN_ZOOM 100
-#define MAX_ZOOM 1000
-#define ZOOM_1X MIN_ZOOM
-
-#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam"
-
-/* internal element names */
-
-#define USE_COLOR_CONVERTER 1
-
-/* FIXME: Make sure this can work with autovideosrc and use that. */
-#define DEFAULT_SRC_VID_SRC "v4l2src"
-
-#define DEFAULT_VIEW_SINK "autovideosink"
-
-/*
- * static helper functions declaration
- */
-
-static void camerabin_setup_src_elements (GstCameraBin * camera);
-
-static gboolean camerabin_create_src_elements (GstCameraBin * camera);
-
-static void camerabin_setup_view_elements (GstCameraBin * camera);
-
-static gboolean camerabin_create_view_elements (GstCameraBin * camera);
-
-static gboolean camerabin_create_elements (GstCameraBin * camera);
-
-static void camerabin_destroy_elements (GstCameraBin * camera);
-
-static void camerabin_dispose_elements (GstCameraBin * camera);
-
-static void gst_camerabin_change_mode (GstCameraBin * camera, gint mode);
-
-static void
-gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name);
-
-static void gst_camerabin_setup_zoom (GstCameraBin * camera);
-
-static GstCaps *gst_camerabin_get_allowed_input_caps (GstCameraBin * camera);
-
-static void gst_camerabin_rewrite_tags (GstCameraBin * camera);
-
-static void
-gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps);
-
-static void gst_camerabin_start_image_capture (GstCameraBin * camera);
-
-static void gst_camerabin_start_video_recording (GstCameraBin * camera);
-
-static gboolean
-gst_camerabin_have_img_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data);
-static gboolean
-gst_camerabin_have_vid_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data);
-
-static void gst_camerabin_reset_to_view_finder (GstCameraBin * camera);
-
-static void gst_camerabin_do_stop (GstCameraBin * camera);
-
-static void
-gst_camerabin_set_allowed_framerate (GstCameraBin * camera,
- GstCaps * filter_caps);
-
-/*
- * GObject callback functions declaration
- */
-
-static void gst_camerabin_base_init (gpointer gclass);
-
-static void gst_camerabin_class_init (GstCameraBinClass * klass);
-
-static void
-gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass);
-
-static void gst_camerabin_dispose (GObject * object);
-
-static void gst_camerabin_finalize (GObject * object);
-
-static void gst_camerabin_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-
-static void gst_camerabin_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static const GValue *gst_camerabin_find_better_framerate (GstCameraBin * camera,
- GstStructure * st, const GValue * orig_framerate);
-/*
- * GstElement function declarations
- */
-
-static GstStateChangeReturn
-gst_camerabin_change_state (GstElement * element, GstStateChange transition);
-
-
-/*
- * GstBin function declarations
- */
-static void
-gst_camerabin_handle_message_func (GstBin * bin, GstMessage * message);
-
-
-/*
- * Action signal function declarations
- */
-
-static void gst_camerabin_user_start (GstCameraBin * camera);
-
-static void gst_camerabin_user_stop (GstCameraBin * camera);
-
-static void gst_camerabin_user_pause (GstCameraBin * camera);
-
-static void
-gst_camerabin_user_res_fps (GstCameraBin * camera, gint width, gint height,
- gint fps_n, gint fps_d);
-
-static void
-gst_camerabin_user_image_res (GstCameraBin * camera, gint width, gint height);
-
-
-/*
- * GST BOILERPLATE and GObject types
- */
-
-static GType
-gst_camerabin_mode_get_type (void)
-{
- static GType gtype = 0;
-
- if (gtype == 0) {
- static const GEnumValue values[] = {
- {MODE_IMAGE, "Still image capture (default)", "mode-image"},
- {MODE_VIDEO, "Video recording", "mode-video"},
- {0, NULL, NULL}
- };
-
- gtype = g_enum_register_static ("GstCameraBinMode", values);
- }
- return gtype;
-}
-
-static gboolean
-gst_camerabin_iface_supported (GstImplementsInterface * iface, GType iface_type)
-{
- GstCameraBin *camera = GST_CAMERABIN (iface);
-
- if (iface_type == GST_TYPE_X_OVERLAY) {
- if (camera->view_sink) {
- return GST_IS_X_OVERLAY (camera->view_sink);
- }
- } else if (iface_type == GST_TYPE_COLOR_BALANCE) {
- if (camera->src_vid_src) {
- return GST_IS_COLOR_BALANCE (camera->src_vid_src);
- }
- } else if (iface_type == GST_TYPE_TAG_SETTER) {
- /* Note: Tag setter elements aren't
- present when image and video bin in NULL */
- GstElement *setter;
- setter = gst_bin_get_by_interface (GST_BIN (camera), iface_type);
- if (setter) {
- gst_object_unref (setter);
- return TRUE;
- } else {
- return FALSE;
- }
- } else if (iface_type == GST_TYPE_PHOTOGRAPHY) {
- if (camera->src_vid_src) {
- return GST_IS_PHOTOGRAPHY (camera->src_vid_src);
- }
- }
-
- return FALSE;
-}
-
-static void
-gst_camerabin_interface_init (GstImplementsInterfaceClass * klass)
-{
- /*
- * default virtual functions
- */
- klass->supported = gst_camerabin_iface_supported;
-}
-
-static void
-camerabin_init_interfaces (GType type)
-{
-
- static const GInterfaceInfo camerabin_info = {
- (GInterfaceInitFunc) gst_camerabin_interface_init,
- NULL,
- NULL,
- };
-
- static const GInterfaceInfo camerabin_xoverlay_info = {
- (GInterfaceInitFunc) gst_camerabin_xoverlay_init,
- NULL,
- NULL,
- };
-
- static const GInterfaceInfo camerabin_color_balance_info = {
- (GInterfaceInitFunc) gst_camerabin_color_balance_init,
- NULL,
- NULL,
- };
-
- static const GInterfaceInfo camerabin_tagsetter_info = {
- NULL,
- NULL,
- NULL,
- };
- static const GInterfaceInfo camerabin_photography_info = {
- (GInterfaceInitFunc) gst_camerabin_photography_init,
- NULL,
- NULL,
- };
-
- g_type_add_interface_static (type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &camerabin_info);
-
- g_type_add_interface_static (type, GST_TYPE_X_OVERLAY,
- &camerabin_xoverlay_info);
-
- g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE,
- &camerabin_color_balance_info);
-
- g_type_add_interface_static (type, GST_TYPE_TAG_SETTER,
- &camerabin_tagsetter_info);
-
- g_type_add_interface_static (type, GST_TYPE_PHOTOGRAPHY,
- &camerabin_photography_info);
-}
-
-GST_BOILERPLATE_FULL (GstCameraBin, gst_camerabin, GstPipeline,
- GST_TYPE_PIPELINE, camerabin_init_interfaces);
-
-/*
- * static helper functions implementation
- */
-
-/*
- * camerabin_setup_src_elements:
- * @camera: camerabin object
- *
- * This function updates camerabin capsfilters according
- * to fps, resolution and zoom that have been configured
- * to camerabin.
- */
-static void
-camerabin_setup_src_elements (GstCameraBin * camera)
-{
- GstStructure *st;
- GstCaps *new_caps;
- gboolean detect_framerate = FALSE;
-
- if (!camera->view_finder_caps) {
- st = gst_structure_from_string (CAMERABIN_DEFAULT_VF_CAPS, NULL);
- } else {
- st = gst_structure_copy (gst_caps_get_structure (camera->view_finder_caps,
- 0));
- }
-
- if (camera->width > 0 && camera->height > 0) {
- gst_structure_set (st,
- "width", G_TYPE_INT, camera->width,
- "height", G_TYPE_INT, camera->height, NULL);
- }
-
- if (camera->fps_n > 0 && camera->fps_d > 0) {
- if (camera->night_mode) {
- GST_WARNING_OBJECT (camera,
- "night mode, lowest allowed fps will be forced");
- camera->pre_night_fps_n = camera->fps_n;
- camera->pre_night_fps_d = camera->fps_d;
- detect_framerate = TRUE;
- } else {
- gst_structure_set (st,
- "framerate", GST_TYPE_FRACTION, camera->fps_n, camera->fps_d, NULL);
- new_caps = gst_caps_new_full (st, NULL);
- }
- } else {
- GST_DEBUG_OBJECT (camera, "no framerate specified");
- detect_framerate = TRUE;
- }
-
- if (detect_framerate) {
- GST_DEBUG_OBJECT (camera, "detecting allowed framerate");
- /* Remove old framerate if any */
- if (gst_structure_has_field (st, "framerate")) {
- gst_structure_remove_field (st, "framerate");
- }
- new_caps = gst_caps_new_full (st, NULL);
-
- /* Set allowed framerate for the resolution */
- gst_camerabin_set_allowed_framerate (camera, new_caps);
- }
-
- /* Set default zoom method */
- g_object_set (camera->src_zoom_scale, "method",
- CAMERABIN_DEFAULT_ZOOM_METHOD, NULL);
-
- gst_caps_replace (&camera->view_finder_caps, new_caps);
-
- /* Set caps for view finder mode */
- gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps);
-}
-
-/*
- * camerabin_create_src_elements:
- * @camera: camerabin object
- *
- * This function creates and links upstream side elements for camerabin.
- * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! out-sel !
- *
- * Returns: TRUE, if elements were successfully created, FALSE otherwise
- */
-static gboolean
-camerabin_create_src_elements (GstCameraBin * camera)
-{
- gboolean ret = FALSE;
- GstBin *cbin = GST_BIN (camera);
- gchar *driver_name = NULL;
-
- if (camera->user_vid_src) {
- camera->src_vid_src = camera->user_vid_src;
-
- if (!gst_camerabin_add_element (cbin, camera->src_vid_src)) {
- camera->src_vid_src = NULL;
- goto done;
- }
- } else if (!(camera->src_vid_src =
- gst_camerabin_create_and_add_element (cbin, DEFAULT_SRC_VID_SRC)))
- goto done;
-#ifdef USE_COLOR_CONVERTER
- if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
- goto done;
-#endif
- if (!(camera->src_filter =
- gst_camerabin_create_and_add_element (cbin, "capsfilter")))
- goto done;
- if (!(camera->src_zoom_crop =
- gst_camerabin_create_and_add_element (cbin, "videocrop")))
- goto done;
- if (!(camera->src_zoom_scale =
- gst_camerabin_create_and_add_element (cbin, "videoscale")))
- goto done;
- if (!(camera->src_zoom_filter =
- gst_camerabin_create_and_add_element (cbin, "capsfilter")))
- goto done;
- if (!(camera->src_out_sel =
- gst_camerabin_create_and_add_element (cbin, "output-selector")))
- goto done;
-
- camera->srcpad_zoom_filter =
- gst_element_get_static_pad (camera->src_zoom_filter, "src");
-
- /* Set default "driver-name" for v4l2camsrc if not set */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src),
- "driver-name")) {
- g_object_get (G_OBJECT (camera->src_vid_src), "driver-name",
- &driver_name, NULL);
- if (!driver_name) {
- g_object_set (G_OBJECT (camera->src_vid_src), "driver-name",
- DEFAULT_V4L2CAMSRC_DRIVER_NAME, NULL);
- }
- }
-
- ret = TRUE;
-done:
- return ret;
-}
-
-/*
- * camerabin_setup_view_elements:
- * @camera: camerabin object
- *
- * This function configures properties for view finder sink element.
- */
-static void
-camerabin_setup_view_elements (GstCameraBin * camera)
-{
- GST_DEBUG_OBJECT (camera, "setting view finder properties");
- g_object_set (G_OBJECT (camera->view_in_sel), "select-all", TRUE, NULL);
- /* Set properties for view finder sink */
- /* Find the actual sink if using bin like autovideosink */
- if (GST_IS_BIN (camera->view_sink)) {
- GList *child = NULL, *children = GST_BIN_CHILDREN (camera->view_sink);
- for (child = children; child != NULL; child = g_list_next (children)) {
- GObject *ch = G_OBJECT (child->data);
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (ch), "sync")) {
- g_object_set (G_OBJECT (ch), "sync", FALSE, "qos", FALSE, "async",
- FALSE, NULL);
- }
- }
- } else {
- g_object_set (G_OBJECT (camera->view_sink), "sync", FALSE, "qos", FALSE,
- "async", FALSE, NULL);
- }
-}
-
-/*
- * camerabin_create_view_elements:
- * @camera: camerabin object
- *
- * This function creates and links downstream side elements for camerabin.
- * ! scale ! cspconv ! view finder sink
- *
- * Returns: TRUE, if elements were successfully created, FALSE otherwise
- */
-static gboolean
-camerabin_create_view_elements (GstCameraBin * camera)
-{
- const GList *pads;
-
- if (!(camera->view_in_sel =
- gst_camerabin_create_and_add_element (GST_BIN (camera),
- "input-selector"))) {
- goto error;
- }
-
- /* Look for recently added input selector sink pad, we need to release it later */
- pads = GST_ELEMENT_PADS (camera->view_in_sel);
- while (pads != NULL
- && (GST_PAD_DIRECTION (GST_PAD (pads->data)) != GST_PAD_SINK)) {
- pads = g_list_next (pads);
- }
- camera->pad_view_img = GST_PAD (pads->data);
-
- if (!(camera->view_scale =
- gst_camerabin_create_and_add_element (GST_BIN (camera),
- "videoscale"))) {
- goto error;
- }
-#ifdef USE_COLOR_CONVERTER
- if (!gst_camerabin_create_and_add_element (GST_BIN (camera),
- "ffmpegcolorspace")) {
- goto error;
- }
-#endif
- if (camera->user_vf_sink) {
- camera->view_sink = camera->user_vf_sink;
- if (!gst_camerabin_add_element (GST_BIN (camera), camera->view_sink)) {
- goto error;
- }
- } else if (!(camera->view_sink =
- gst_camerabin_create_and_add_element (GST_BIN (camera),
- DEFAULT_VIEW_SINK))) {
- goto error;
- }
-
- return TRUE;
-error:
- return FALSE;
-}
-
-/*
- * camerabin_create_elements:
- * @camera: camerabin object
- *
- * This function creates and links all elements for camerabin,
- *
- * Returns: TRUE, if elements were successfully created, FALSE otherwise
- */
-static gboolean
-camerabin_create_elements (GstCameraBin * camera)
-{
- gboolean ret = FALSE;
- GstPadLinkReturn link_ret = GST_PAD_LINK_REFUSED;
- GstPad *unconnected_pad;
-
- GST_LOG_OBJECT (camera, "creating elems");
-
- /* Create "src" elements */
- if (!camerabin_create_src_elements (camera)) {
- goto done;
- }
-
- /* Add image bin */
- camera->pad_src_img =
- gst_element_get_request_pad (camera->src_out_sel, "src%d");
- if (!gst_camerabin_add_element (GST_BIN (camera), camera->imgbin)) {
- goto done;
- }
- gst_pad_add_buffer_probe (camera->pad_src_img,
- G_CALLBACK (gst_camerabin_have_img_buffer), camera);
-
- /* Create view finder elements, this also links it to image bin */
- if (!camerabin_create_view_elements (camera)) {
- GST_WARNING_OBJECT (camera, "creating view failed");
- goto done;
- }
-
- /* Link output selector ! view_finder */
- camera->pad_src_view =
- gst_element_get_request_pad (camera->src_out_sel, "src%d");
- camera->pad_view_src =
- gst_element_get_request_pad (camera->view_in_sel, "sink%d");
- link_ret = gst_pad_link (camera->pad_src_view, camera->pad_view_src);
- if (GST_PAD_LINK_FAILED (link_ret)) {
- GST_ELEMENT_ERROR (camera, CORE, NEGOTIATION,
- ("linking view finder failed"), (NULL));
- goto done;
- }
-
- /* Set view finder active as default */
- g_object_set (G_OBJECT (camera->src_out_sel), "active-pad",
- camera->pad_src_view, NULL);
-
- /* Add video bin */
- camera->pad_src_vid =
- gst_element_get_request_pad (camera->src_out_sel, "src%d");
- if (!gst_camerabin_add_element (GST_BIN (camera), camera->vidbin)) {
- goto done;
- }
- gst_pad_add_buffer_probe (camera->pad_src_vid,
- G_CALLBACK (gst_camerabin_have_vid_buffer), camera);
-
- /* Link video bin ! view finder */
- // unconnected_pad = gst_bin_find_unlinked_pad (GST_BIN (camera), GST_PAD_SRC);
- unconnected_pad = gst_bin_find_unconnected_pad (GST_BIN (camera), GST_PAD_SRC);
- camera->pad_view_vid =
- gst_element_get_request_pad (camera->view_in_sel, "sink%d");
- link_ret = gst_pad_link (unconnected_pad, camera->pad_view_vid);
- gst_object_unref (unconnected_pad);
- if (GST_PAD_LINK_FAILED (link_ret)) {
- GST_ELEMENT_ERROR (camera, CORE, NEGOTIATION, (NULL),
- ("linking video bin and view finder failed"));
- goto done;
- }
-
- ret = TRUE;
-
-done:
-
- if (FALSE == ret)
- camerabin_destroy_elements (camera);
-
- return ret;
-}
-
-/*
- * camerabin_destroy_elements:
- * @camera: camerabin object
- *
- * This function removes all elements from camerabin.
- */
-static void
-camerabin_destroy_elements (GstCameraBin * camera)
-{
- GST_DEBUG_OBJECT (camera, "destroying elements");
-
- /* Release request pads */
- if (camera->pad_view_vid) {
- gst_element_release_request_pad (camera->view_in_sel, camera->pad_view_vid);
- camera->pad_view_vid = NULL;
- }
- if (camera->pad_src_vid) {
- gst_element_release_request_pad (camera->src_out_sel, camera->pad_src_vid);
- camera->pad_src_vid = NULL;
- }
- if (camera->pad_view_img) {
- gst_element_release_request_pad (camera->view_in_sel, camera->pad_view_img);
- camera->pad_view_img = NULL;
- }
- if (camera->pad_src_img) {
- gst_element_release_request_pad (camera->src_out_sel, camera->pad_src_img);
- camera->pad_src_img = NULL;
- }
- if (camera->pad_view_src) {
- gst_element_release_request_pad (camera->view_in_sel, camera->pad_view_src);
- camera->pad_view_src = NULL;
- }
- if (camera->pad_src_view) {
- gst_element_release_request_pad (camera->src_out_sel, camera->pad_src_view);
- camera->pad_src_view = NULL;
- }
-
- camera->view_sink = NULL;
- camera->view_scale = NULL;
- camera->view_in_sel = NULL;
-
- camera->src_out_sel = NULL;
- camera->src_filter = NULL;
- camera->src_zoom_crop = NULL;
- camera->src_zoom_scale = NULL;
- camera->src_zoom_filter = NULL;
- camera->src_vid_src = NULL;
-
- camera->active_bin = NULL;
-
- /* Remove elements */
- gst_camerabin_remove_elements_from_bin (GST_BIN (camera));
-}
-
-/*
- * camerabin_dispose_elements:
- * @camera: camerabin object
- *
- * This function releases all allocated camerabin resources.
- */
-static void
-camerabin_dispose_elements (GstCameraBin * camera)
-{
- if (camera->capture_mutex) {
- g_mutex_free (camera->capture_mutex);
- camera->capture_mutex = NULL;
- }
- if (camera->cond) {
- g_cond_free (camera->cond);
- camera->cond = NULL;
- }
- if (camera->filename) {
- g_string_free (camera->filename, TRUE);
- camera->filename = NULL;
- }
- /* Unref user set elements */
- if (camera->user_vf_sink) {
- gst_object_unref (camera->user_vf_sink);
- camera->user_vf_sink = NULL;
- }
- if (camera->user_vid_src) {
- gst_object_unref (camera->user_vid_src);
- camera->user_vid_src = NULL;
- }
-
- if (camera->image_capture_caps) {
- gst_caps_unref (camera->image_capture_caps);
- camera->image_capture_caps = NULL;
- }
-
- if (camera->view_finder_caps) {
- gst_caps_unref (camera->view_finder_caps);
- camera->view_finder_caps = NULL;
- }
-
- if (camera->allowed_caps) {
- gst_caps_unref (camera->allowed_caps);
- camera->allowed_caps = NULL;
- }
-}
-
-/*
- * gst_camerabin_image_capture_continue:
- * @camera: camerabin object
- * @filename: new filename set by user
- * @cont: TRUE to continue image capture, FALSE otherwise
- *
- * Check if user wants to continue image capturing by using g_signal.
- */
-static void
-gst_camerabin_image_capture_continue (GstCameraBin * camera, GString * filename,
- gboolean * cont)
-{
- GST_DEBUG_OBJECT (camera, "emitting img_done signal, filename: %s",
- filename->str);
- g_signal_emit (G_OBJECT (camera), camerabin_signals[IMG_DONE_SIGNAL], 0,
- filename, cont);
-
- GST_DEBUG_OBJECT (camera, "emitted img_done, new filename:%s, continue:%d",
- filename->str, *cont);
-}
-
-/*
- * gst_camerabin_change_mode:
- * @camera: camerabin object
- * @mode: image or video mode
- *
- * Change camerabin mode between image and video capture.
- * Changing mode will stop ongoing capture.
- */
-static void
-gst_camerabin_change_mode (GstCameraBin * camera, gint mode)
-{
- if (camera->mode != mode || !camera->active_bin) {
- GST_DEBUG_OBJECT (camera, "setting mode: %d", mode);
- /* Interrupt ongoing capture */
- gst_camerabin_do_stop (camera);
- camera->mode = mode;
- if (camera->active_bin) {
- gst_element_set_state (camera->active_bin, GST_STATE_NULL);
- }
- if (camera->mode == MODE_IMAGE) {
- camera->active_bin = camera->imgbin;
- } else if (camera->mode == MODE_VIDEO) {
- camera->active_bin = camera->vidbin;
- }
- gst_camerabin_reset_to_view_finder (camera);
- }
-}
-
-/*
- * gst_camerabin_change_filename:
- * @camera: camerabin object
- * @name: new filename for capture
- *
- * Change filename for image or video capture.
- * Changing filename will stop ongoing capture.
- */
-static void
-gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name)
-{
- if (0 != strcmp (camera->filename->str, name)) {
- GST_DEBUG_OBJECT (camera, "changing filename from %s to %s",
- camera->filename->str, name);
- /* Interrupt ongoing capture */
- gst_camerabin_do_stop (camera);
- gst_camerabin_reset_to_view_finder (camera);
-
- if (camera->active_bin) {
- g_object_set (G_OBJECT (camera->active_bin), "filename", name, NULL);
- }
-
- g_string_assign (camera->filename, name);
- }
-}
-
-/*
- * gst_camerabin_setup_zoom:
- * @camera: camerabin object
- *
- * Apply zoom configured to camerabin to capture.
- */
-static void
-gst_camerabin_setup_zoom (GstCameraBin * camera)
-{
- gint zoom;
- gboolean done = FALSE;
-
- g_return_if_fail (camera != NULL);
- g_return_if_fail (camera->src_zoom_crop != NULL);
-
- zoom = g_atomic_int_get (&camera->zoom);
-
- g_return_if_fail (zoom);
-
- if (GST_IS_ELEMENT (camera->src_vid_src) &&
- gst_element_implements_interface (camera->src_vid_src,
- GST_TYPE_PHOTOGRAPHY)) {
- /* Try setting (hardware) zoom using photography interface */
- GstPhotography *photo;
- GstPhotoCaps pcaps;
-
- photo = GST_PHOTOGRAPHY (camera->src_vid_src);
- pcaps = gst_photography_get_capabilities (photo);
-
- if (pcaps & GST_PHOTOGRAPHY_CAPS_ZOOM) {
- done = gst_photography_set_zoom (photo, (gfloat) zoom / 100.0);
- }
- }
-
- if (!done) {
- /* Update capsfilters to apply the (software) zoom */
- gint w2_crop = 0;
- gint h2_crop = 0;
- GstPad *pad_zoom_sink = NULL;
-
- GST_INFO_OBJECT (camera, "zoom: %d, orig size: %dx%d", zoom,
- camera->width, camera->height);
-
- if (zoom != ZOOM_1X) {
- w2_crop = (camera->width - (camera->width * ZOOM_1X / zoom)) / 2;
- h2_crop = (camera->height - (camera->height * ZOOM_1X / zoom)) / 2;
- }
-
- pad_zoom_sink = gst_element_get_static_pad (camera->src_zoom_crop, "sink");
-
- GST_INFO_OBJECT (camera,
- "sw cropping: left:%d, right:%d, top:%d, bottom:%d", w2_crop, w2_crop,
- h2_crop, h2_crop);
-
- GST_PAD_STREAM_LOCK (pad_zoom_sink);
- g_object_set (camera->src_zoom_crop, "left", w2_crop, "right", w2_crop,
- "top", h2_crop, "bottom", h2_crop, NULL);
-
- GST_PAD_STREAM_UNLOCK (pad_zoom_sink);
- gst_object_unref (pad_zoom_sink);
- }
- GST_LOG_OBJECT (camera, "zoom set");
-}
-
-/*
- * gst_camerabin_get_allowed_input_caps:
- * @camera: camerabin object
- *
- * Retrieve caps from videosrc describing formats it supports
- *
- * Returns: caps object from videosrc
- */
-static GstCaps *
-gst_camerabin_get_allowed_input_caps (GstCameraBin * camera)
-{
- GstCaps *caps = NULL;
- GstPad *pad = NULL, *peer_pad = NULL;
- GstState state;
- gboolean temp_videosrc_pause = FALSE;
- GstElement *videosrc;
-
- g_return_val_if_fail (camera != NULL, NULL);
-
- videosrc = camera->src_vid_src ? camera->src_vid_src : camera->user_vid_src;
-
- if (!videosrc) {
- GST_WARNING_OBJECT (camera, "no videosrc, can't get allowed caps");
- goto failed;
- }
-
- if (camera->allowed_caps) {
- GST_DEBUG_OBJECT (camera, "returning cached caps");
- goto done;
- }
-
- pad = gst_element_get_static_pad (videosrc, "src");
-
- if (!pad) {
- GST_WARNING_OBJECT (camera, "no srcpad in videosrc");
- goto failed;
- }
-
- state = GST_STATE (videosrc);
-
- /* Make this function work also in READY and NULL state */
- if (state == GST_STATE_READY || state == GST_STATE_NULL) {
- GST_DEBUG_OBJECT (camera, "setting videosrc to paused temporarily");
- temp_videosrc_pause = TRUE;
- peer_pad = gst_pad_get_peer (pad);
- if (peer_pad) {
- gst_pad_unlink (pad, peer_pad);
- }
- /* Set videosrc to PAUSED to open video device */
- gst_element_set_locked_state (videosrc, TRUE);
- gst_element_set_state (videosrc, GST_STATE_PAUSED);
- }
-
- camera->allowed_caps = gst_pad_get_caps (pad);
-
- /* Restore state and re-link if necessary */
- if (temp_videosrc_pause) {
- GST_DEBUG_OBJECT (camera, "restoring videosrc state %d", state);
- /* Reset videosrc to NULL state, some drivers seem to need this */
- gst_element_set_state (videosrc, GST_STATE_NULL);
- gst_element_set_state (videosrc, state);
- if (peer_pad) {
- gst_pad_link (pad, peer_pad);
- gst_object_unref (peer_pad);
- }
- gst_element_set_locked_state (videosrc, FALSE);
- }
-
- gst_object_unref (pad);
-
-done:
- if (camera->allowed_caps) {
- caps = gst_caps_copy (camera->allowed_caps);
- }
-failed:
- GST_INFO_OBJECT (camera, "allowed caps:%" GST_PTR_FORMAT, caps);
- return caps;
-}
-
-/*
- * gst_camerabin_rewrite_tags_to_bin:
- * @bin: bin holding tag setter elements
- * @list: tag list to be written
- *
- * This function looks for certain tag setters from given bin
- * and REPLACES ALL setter tags with given tag list
- *
- */
-static void
-gst_camerabin_rewrite_tags_to_bin (GstBin * bin, const GstTagList * list)
-{
- GstElement *setter;
- GstElementFactory *setter_factory;
- const gchar *klass;
- GstIterator *iter;
- GstIteratorResult res = GST_ITERATOR_OK;
- gpointer data;
-
- iter = gst_bin_iterate_all_by_interface (bin, GST_TYPE_TAG_SETTER);
-
- while (res == GST_ITERATOR_OK || res == GST_ITERATOR_RESYNC) {
- res = gst_iterator_next (iter, &data);
- switch (res) {
- case GST_ITERATOR_DONE:
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- GST_WARNING ("error iterating tag setters");
- break;
- case GST_ITERATOR_OK:
- setter = GST_ELEMENT (data);
- GST_LOG ("iterating tag setters: %" GST_PTR_FORMAT, setter);
- setter_factory = gst_element_get_factory (setter);
- klass = gst_element_factory_get_klass (setter_factory);
- /* FIXME: check if tags should be written to all tag setters,
- set tags only to Muxer elements for now */
- if (g_strrstr (klass, "Muxer")) {
- GST_DEBUG ("replacement tags %" GST_PTR_FORMAT, list);
- gst_tag_setter_merge_tags (GST_TAG_SETTER (setter), list,
- GST_TAG_MERGE_REPLACE_ALL);
- }
- gst_object_unref (setter);
- break;
- default:
- break;
- }
- }
-
- gst_iterator_free (iter);
-}
-
-/*
- * gst_camerabin_get_internal_tags:
- * @camera: the camera bin element
- *
- * Returns tag list containing metadata from camerabin
- * and it's elements
- */
-static GstTagList *
-gst_camerabin_get_internal_tags (GstCameraBin * camera)
-{
- GstTagList *list = gst_tag_list_new ();
- GstColorBalance *balance = NULL;
- const GList *controls = NULL, *item;
- GstColorBalanceChannel *channel;
- gint min_value, max_value, mid_value, cur_value;
-
-
- if (camera->active_bin == camera->vidbin) {
- /* FIXME: check if internal video tag setting is needed */
- goto done;
- }
-
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "image-width", camera->width, "image-height", camera->height, NULL);
-
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "capture-digital-zoom", camera->zoom, 100, NULL);
-
- if (gst_element_implements_interface (GST_ELEMENT (camera),
- GST_TYPE_COLOR_BALANCE)) {
- balance = GST_COLOR_BALANCE (camera);
- }
-
- if (balance) {
- controls = gst_color_balance_list_channels (balance);
- }
- for (item = controls; item; item = g_list_next (item)) {
- channel = item->data;
- min_value = channel->min_value;
- max_value = channel->max_value;
- /* the default value would probably better */
- mid_value = min_value + ((max_value - min_value) / 2);
- cur_value = gst_color_balance_get_value (balance, channel);
-
- if (!strcasecmp (channel->label, "brightness")) {
- /* The value of brightness. The unit is the APEX value (Additive System of Photographic Exposure).
- * Ordinarily it is given in the range of -99.99 to 99.99. Note that
- * if the numerator of the recorded value is 0xFFFFFFFF, Unknown shall be indicated.
- *
- * BrightnessValue (Bv) = log2 ( B/NK )
- * Note that: B:cd/cm² (candela per square centimeter), N,K: constant
- *
- * http://johnlind.tripod.com/science/scienceexposure.html
- *
- */
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "capture-brightness", cur_value, 1, NULL);
- } else if (!strcasecmp (channel->label, "contrast")) {
- /* 0 = Normal, 1 = Soft, 2 = Hard */
-
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "capture-contrast",
- (cur_value == mid_value) ? 0 : ((cur_value < mid_value) ? 1 : 2),
- NULL);
- } else if (!strcasecmp (channel->label, "gain")) {
- /* 0 = Normal, 1 = Low Up, 2 = High Up, 3 = Low Down, 4 = Hight Down */
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "capture-gain",
- (guint) (cur_value == mid_value) ? 0 : ((cur_value <
- mid_value) ? 1 : 3), NULL);
- } else if (!strcasecmp (channel->label, "saturation")) {
- /* 0 = Normal, 1 = Low, 2 = High */
- gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
- "capture-saturation",
- (cur_value == mid_value) ? 0 : ((cur_value < mid_value) ? 1 : 2),
- NULL);
- }
- }
-
-done:
-
- return list;
-}
-
-/*
- * gst_camerabin_rewrite_tags:
- * @camera: the camera bin element
- *
- * Merges application set tags to camerabin internal tags,
- * and writes them using image or video bin tag setters.
- */
-static void
-gst_camerabin_rewrite_tags (GstCameraBin * camera)
-{
- const GstTagList *app_tag_list = NULL;
- GstTagList *list = NULL;
-
- /* Get application set tags */
- app_tag_list = gst_tag_setter_get_tag_list (GST_TAG_SETTER (camera));
-
- /* Get tags from camerabin and it's elements */
- list = gst_camerabin_get_internal_tags (camera);
-
- if (app_tag_list) {
- gst_tag_list_insert (list, app_tag_list, GST_TAG_MERGE_REPLACE);
- }
-
- /* Write tags */
- gst_camerabin_rewrite_tags_to_bin (GST_BIN (camera->active_bin), list);
-
- gst_tag_list_free (list);
-}
-
-/*
- * gst_camerabin_set_capsfilter_caps:
- * @camera: camerabin object
- * @new_caps: pointer to caps object to set
- *
- * Set given caps to camerabin capsfilters.
- */
-static void
-gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps)
-{
- GstStructure *st;
-
- GST_INFO_OBJECT (camera, "new_caps:%" GST_PTR_FORMAT, new_caps);
-
- st = gst_caps_get_structure (new_caps, 0);
-
- gst_structure_get_int (st, "width", &camera->width);
- gst_structure_get_int (st, "height", &camera->height);
-
- if (gst_structure_has_field (st, "framerate")) {
- gst_structure_get_fraction (st, "framerate", &camera->fps_n,
- &camera->fps_d);
- }
-
- /* Update zoom */
- gst_camerabin_setup_zoom (camera);
-
- /* Update capsfilters */
- g_object_set (G_OBJECT (camera->src_filter), "caps", new_caps, NULL);
- g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL);
-}
-
-/*
- * img_capture_prepared:
- * @data: camerabin object
- *
- * Callback which is called after image capture has been prepared.
- */
-static void
-img_capture_prepared (gpointer data)
-{
- GstCameraBin *camera = GST_CAMERABIN (data);
-
- GST_INFO_OBJECT (camera, "image capture prepared");
-
- if (camera->image_capture_caps) {
- /* Set capsfilters to match arriving image data */
- gst_camerabin_set_capsfilter_caps (camera, camera->image_capture_caps);
- }
-
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
- "active-pad", camera->pad_src_img, NULL);
- gst_camerabin_rewrite_tags (camera);
- gst_element_set_state (GST_ELEMENT (camera->imgbin), GST_STATE_PLAYING);
-}
-
-/*
- * gst_camerabin_start_image_capture:
- * @camera: camerabin object
- *
- * Initiates image capture.
- */
-static void
-gst_camerabin_start_image_capture (GstCameraBin * camera)
-{
- GstStateChangeReturn state_ret;
- gboolean wait_for_prepare = FALSE;
- gint width = 0, height = 0, fps_n = 0, fps_d = 0;
- GstStructure *st;
-
- GST_INFO_OBJECT (camera, "starting image capture");
-
- if (GST_IS_ELEMENT (camera->src_vid_src) &&
- gst_element_implements_interface (camera->src_vid_src,
- GST_TYPE_PHOTOGRAPHY)) {
- /* Start image capture preparations using photography iface */
- wait_for_prepare = TRUE;
- g_mutex_lock (camera->capture_mutex);
- if (camera->image_capture_caps) {
- st = gst_caps_get_structure (camera->image_capture_caps, 0);
- } else {
- st = gst_caps_get_structure (camera->view_finder_caps, 0);
- }
- gst_structure_get_int (st, "width", &width);
- gst_structure_get_int (st, "height", &height);
- gst_structure_get_fraction (st, "framerate", &fps_n, &fps_d);
- /* Set image capture resolution and frame rate */
- g_signal_emit_by_name (camera->src_vid_src, "user-res-fps",
- width, height, fps_n, fps_d, 0);
-
- /* Enable still image capture mode in v4l2camsrc */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src),
- "capture-mode")) {
- g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 1, NULL);
- }
-
- /* Start preparations for image capture */
- gst_photography_prepare_for_capture (GST_PHOTOGRAPHY (camera->src_vid_src),
- (GstPhotoCapturePrepared) img_capture_prepared, camera);
- camera->capturing = TRUE;
- g_mutex_unlock (camera->capture_mutex);
- }
-
- if (!wait_for_prepare) {
- gst_camerabin_rewrite_tags (camera);
- state_ret = gst_element_set_state (camera->imgbin, GST_STATE_PLAYING);
- if (state_ret != GST_STATE_CHANGE_FAILURE) {
- g_mutex_lock (camera->capture_mutex);
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE,
- "active-pad", camera->pad_src_img, NULL);
- camera->capturing = TRUE;
- g_mutex_unlock (camera->capture_mutex);
- } else {
- GST_WARNING_OBJECT (camera, "imagebin state change failed");
- gst_element_set_state (camera->imgbin, GST_STATE_NULL);
- }
- }
-}
-
-/*
- * gst_camerabin_start_video_recording:
- * @camera: camerabin object
- *
- * Initiates video recording.
- */
-static void
-gst_camerabin_start_video_recording (GstCameraBin * camera)
-{
- GstStateChangeReturn state_ret;
- /* FIXME: how to ensure resolution and fps is supported by CPU?
- * use a queue overrun signal?
- */
- GST_INFO_OBJECT (camera, "starting video capture");
-
- gst_camerabin_rewrite_tags (camera);
-
- /* Pause the pipeline in order to distribute new clock in paused_to_playing */
- /* audio src timestamps will be 0 without state change to READY. ??? */
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_READY);
- gst_element_set_locked_state (camera->vidbin, FALSE);
- state_ret = gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PAUSED);
-
- if (state_ret != GST_STATE_CHANGE_FAILURE) {
- g_mutex_lock (camera->capture_mutex);
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
- "active-pad", camera->pad_src_vid, NULL);
-
- /* Enable video mode in v4l2camsrc */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src),
- "capture-mode")) {
- g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 2, NULL);
- }
-
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING);
- gst_element_set_locked_state (camera->vidbin, TRUE);
- camera->capturing = TRUE;
- g_mutex_unlock (camera->capture_mutex);
- } else {
- GST_WARNING_OBJECT (camera, "videobin state change failed");
- gst_element_set_state (camera->vidbin, GST_STATE_NULL);
- gst_camerabin_reset_to_view_finder (camera);
- }
-}
-
-/*
- * gst_camerabin_send_video_eos:
- * @camera: camerabin object
- *
- * Generate and send eos event to video bin in order to
- * finish recording properly.
- */
-static void
-gst_camerabin_send_video_eos (GstCameraBin * camera)
-{
- GstPad *videopad;
-
- g_return_if_fail (camera != NULL);
-
- /* Send eos event to video bin */
- GST_INFO_OBJECT (camera, "sending eos to videobin");
- videopad = gst_element_get_static_pad (camera->vidbin, "sink");
- gst_pad_send_event (videopad, gst_event_new_eos ());
- gst_object_unref (videopad);
-}
-
-/*
- * image_pad_blocked:
- * @pad: pad to block/unblock
- * @blocked: TRUE to block, FALSE to unblock
- * @u_data: camera bin object
- *
- * Sends eos event to image bin if blocking pad leading to image bin.
- * The pad will be unblocked when image bin posts eos message.
- */
-static void
-image_pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
-{
- GstCameraBin *camera;
-
- camera = (GstCameraBin *) user_data;
-
- GST_DEBUG_OBJECT (camera, "%s %s:%s",
- blocked ? "blocking" : "unblocking", GST_DEBUG_PAD_NAME (pad));
-
- if (blocked && (pad == camera->pad_src_img)) {
- /* Send eos and block until image bin reaches eos */
- GST_DEBUG_OBJECT (camera, "sending eos to image bin");
- gst_element_send_event (camera->imgbin, gst_event_new_eos ());
- }
-}
-
-/*
- * gst_camerabin_have_img_buffer:
- * @pad: output-selector src pad leading to image bin
- * @buffer: still image frame
- * @u_data: camera bin object
- *
- * Buffer probe called before sending each buffer to image bin.
- *
- * First buffer is always passed directly to image bin. Then pad
- * is blocked in order to interleave buffers with eos events.
- * Interleaving eos events and buffers is needed when we have
- * decoupled elements in the image bin capture pipeline.
- * After image bin posts eos message, then pad is unblocked.
- * Next, image bin is changed to READY state in order to save the
- * file and the application is allowed to decide whether to
- * continue image capture. If yes, only then the next buffer is
- * passed to image bin.
- */
-static gboolean
-gst_camerabin_have_img_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data)
-{
- GstCameraBin *camera = (GstCameraBin *) u_data;
- gboolean ret = TRUE;
-
- GST_LOG ("got buffer #%d %p with size %d", camera->num_img_buffers,
- buffer, GST_BUFFER_SIZE (buffer));
-
- /* Image filename should be set by now */
- if (g_str_equal (camera->filename->str, "")) {
- GST_DEBUG_OBJECT (camera, "filename not set, dropping buffer");
- ret = FALSE;
- goto done;
- }
-
- /* Check for first buffer after capture start, we want to
- pass it forward directly. */
- if (!camera->num_img_buffers) {
- /* Restore filter caps for view finder mode if necessary.
- The v4l2camsrc switches automatically to view finder
- resolution after hi-res still image capture. */
- if (camera->image_capture_caps) {
- gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps);
- }
- goto done;
- }
-
- /* Close the file of saved image */
- gst_element_set_state (camera->imgbin, GST_STATE_READY);
-
- /* Check if the application wants to continue */
- gst_camerabin_image_capture_continue (camera, camera->filename, &ret);
-
- if (ret && !camera->stop_requested) {
- GST_DEBUG_OBJECT (camera, "capturing image \"%s\"", camera->filename->str);
- g_object_set (G_OBJECT (camera->imgbin), "filename",
- camera->filename->str, NULL);
- gst_element_set_state (camera->imgbin, GST_STATE_PLAYING);
- } else {
- GST_DEBUG_OBJECT (camera, "not continuing (cont:%d, stop_req:%d)",
- ret, camera->stop_requested);
- /* Reset filename to force application set new filename */
- g_string_assign (camera->filename, "");
-
- /* Block dataflow to the output-selector to show preview image in
- view finder. Continue and unblock when capture is stopped */
- gst_pad_set_blocked_async (camera->srcpad_zoom_filter, TRUE,
- (GstPadBlockCallback) image_pad_blocked, camera);
- ret = FALSE; /* Drop the buffer */
-
- g_mutex_lock (camera->capture_mutex);
- camera->capturing = FALSE;
- g_cond_signal (camera->cond);
- g_mutex_unlock (camera->capture_mutex);
- }
-
-done:
-
- if (ret) {
- camera->num_img_buffers++;
- /* Block when next buffer arrives, we want to push eos event
- between frames and make sure that eos reaches the filesink
- before processing the next buffer. */
- gst_pad_set_blocked_async (pad, TRUE,
- (GstPadBlockCallback) image_pad_blocked, camera);
- }
-
- return ret;
-}
-
-/*
- * gst_camerabin_have_vid_buffer:
- * @pad: output-selector src pad leading to video bin
- * @buffer: buffer pushed to the pad
- * @u_data: camerabin object
- *
- * Buffer probe for src pad leading to video bin.
- * Sends eos event to video bin if stop requested and drops
- * all buffers after this.
- */
-static gboolean
-gst_camerabin_have_vid_buffer (GstPad * pad, GstBuffer * buffer,
- gpointer u_data)
-{
- GstCameraBin *camera = (GstCameraBin *) u_data;
- gboolean ret = TRUE;
- GST_LOG ("got video buffer %p with size %d",
- buffer, GST_BUFFER_SIZE (buffer));
- if (camera->stop_requested) {
- gst_camerabin_send_video_eos (camera);
- ret = FALSE; /* Drop buffer */
- }
-
- return ret;
-}
-
-/*
- * gst_camerabin_reset_to_view_finder:
- * @camera: camerabin object
- *
- * Stop capturing and set camerabin to view finder mode.
- * Reset capture counters and flags.
- */
-static void
-gst_camerabin_reset_to_view_finder (GstCameraBin * camera)
-{
- GstStateChangeReturn state_ret;
- GST_DEBUG_OBJECT (camera, "resetting");
-
- /* Set active bin to READY state */
- if (camera->active_bin) {
- state_ret = gst_element_set_state (camera->active_bin, GST_STATE_READY);
- if (state_ret == GST_STATE_CHANGE_FAILURE) {
- GST_WARNING_OBJECT (camera, "state change failed");
- gst_element_set_state (camera->active_bin, GST_STATE_NULL);
- camera->active_bin = NULL;
- }
- }
-
- /* Reset counters and flags */
- camera->num_img_buffers = 0;
- camera->stop_requested = FALSE;
- camera->paused = FALSE;
-
- if (camera->src_out_sel) {
- /* Set selector to forward data to view finder */
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
- "active-pad", camera->pad_src_view, NULL);
- }
-
- /* Unblock, if dataflow to output-selector is blocked due to image preview */
- if (camera->srcpad_zoom_filter &&
- gst_pad_is_blocked (camera->srcpad_zoom_filter)) {
- gst_pad_set_blocked_async (camera->srcpad_zoom_filter, FALSE,
- (GstPadBlockCallback) image_pad_blocked, camera);
- }
- /* Unblock, if dataflow to image bin is blocked due to waiting for eos */
- if (camera->pad_src_img && gst_pad_is_blocked (camera->pad_src_img)) {
- gst_pad_set_blocked_async (camera->pad_src_img, FALSE,
- (GstPadBlockCallback) image_pad_blocked, camera);
- }
-
- /* Enable view finder mode in v4l2camsrc */
- if (camera->src_vid_src &&
- g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src),
- "capture-mode")) {
- g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 0, NULL);
- }
-
- GST_DEBUG_OBJECT (camera, "reset done");
-}
-
-/*
- * gst_camerabin_do_stop:
- * @camera: camerabin object
- *
- * Raise flag to indicate to image and video bin capture stop.
- * Stopping paused video recording handled as a special case.
- * Wait for ongoing capturing to finish.
- */
-static void
-gst_camerabin_do_stop (GstCameraBin * camera)
-{
- g_mutex_lock (camera->capture_mutex);
- if (camera->capturing) {
- GST_DEBUG_OBJECT (camera, "mark stop");
- camera->stop_requested = TRUE;
-
- /* Take special care when stopping paused video capture */
- if ((camera->active_bin == camera->vidbin) && camera->paused) {
- /* Send eos event to video bin before setting it to playing */
- gst_camerabin_send_video_eos (camera);
- /* We must change to playing now in order to get video bin eos events
- and buffered data through and finish recording properly */
- gst_element_set_state (GST_ELEMENT (camera->vidbin), GST_STATE_PLAYING);
- camera->paused = FALSE;
- }
-
- GST_DEBUG_OBJECT (camera, "waiting for capturing to finish");
- g_cond_wait (camera->cond, camera->capture_mutex);
- GST_DEBUG_OBJECT (camera, "capturing finished");
- }
- g_mutex_unlock (camera->capture_mutex);
-}
-
-/*
- * gst_camerabin_default_signal_img_done:
- * @camera: camerabin object
- * @fname: new filename
- *
- * Default handler for #GstCameraBin::img-done signal,
- * stops always capture.
- *
- * Returns: FALSE always
- */
-static gboolean
-gst_camerabin_default_signal_img_done (GstCameraBin * camera, GString * fname)
-{
- return FALSE;
-}
-
-/*
- * gst_camerabin_set_allowed_framerate:
- * @camera: camerabin object
- * @filter_caps: update allowed framerate to these caps
- *
- * Find allowed frame rate from video source that matches with
- * resolution in @filter_caps. Set found frame rate to @filter_caps.
- */
-static void
-gst_camerabin_set_allowed_framerate (GstCameraBin * camera,
- GstCaps * filter_caps)
-{
- GstStructure *structure;
- GstCaps *allowed_caps = NULL, *intersect = NULL;
- const GValue *framerate = NULL;
- guint caps_size, i;
-
- /* Get supported caps from video src that matches with new filter caps */
- GST_INFO_OBJECT (camera, "filter caps:%" GST_PTR_FORMAT, filter_caps);
- allowed_caps = gst_camerabin_get_allowed_input_caps (camera);
- intersect = gst_caps_intersect (allowed_caps, filter_caps);
- GST_INFO_OBJECT (camera, "intersect caps:%" GST_PTR_FORMAT, intersect);
-
- /* Find the best framerate from the caps */
- caps_size = gst_caps_get_size (intersect);
- for (i = 0; i < caps_size; i++) {
- structure = gst_caps_get_structure (intersect, i);
- framerate =
- gst_camerabin_find_better_framerate (camera, structure, framerate);
- }
-
- if (GST_VALUE_HOLDS_FRACTION (framerate)) {
- gst_caps_set_simple (filter_caps,
- "framerate", GST_TYPE_FRACTION,
- gst_value_get_fraction_numerator (framerate),
- gst_value_get_fraction_denominator (framerate), NULL);
- }
-
- if (allowed_caps) {
- gst_caps_unref (allowed_caps);
- }
- if (intersect) {
- gst_caps_unref (intersect);
- }
-}
-
-
-/**
- * get_srcpad_current_format:
- * @element: element to get the format from
- *
- * Helper function to get the negotiated fourcc
- * format from @element src pad.
- *
- * Returns: negotiated format (fourcc), 0 if not found
- */
-static guint32
-get_srcpad_current_format (GstElement * element)
-{
- GstPad *srcpad = NULL;
- GstCaps *srccaps = NULL;
- GstStructure *structure;
- guint32 format = 0;
-
- g_return_val_if_fail (element != NULL, 0);
-
- if ((srcpad = gst_element_get_static_pad (element, "src")) == NULL) {
- goto no_pad;
- }
-
- if ((srccaps = gst_pad_get_negotiated_caps (srcpad)) == NULL) {
- goto no_caps;
- }
-
- GST_LOG ("negotiated caps %" GST_PTR_FORMAT, srccaps);
-
- structure = gst_caps_get_structure (srccaps, 0);
- if (gst_structure_has_field (structure, "format")) {
- gst_structure_get_fourcc (structure, "format", &format);
- }
-
- gst_caps_unref (srccaps);
-no_caps:
- gst_object_unref (srcpad);
-no_pad:
- GST_DEBUG ("current format for %" GST_PTR_FORMAT ": %" GST_FOURCC_FORMAT,
- element, GST_FOURCC_ARGS (format));
- return format;
-}
-
-/*
- * gst_camerabin_find_better_framerate:
- * @camera: camerabin object
- * @st: structure that contains framerate candidates
- * @orig_framerate: best framerate so far
- *
- * Looks for framerate better than @orig_framerate from @st structure.
- * In night mode lowest framerate is considered best, otherwise highest is
- * best.
- *
- * Returns: @orig_framerate or better if found
- */
-static const GValue *
-gst_camerabin_find_better_framerate (GstCameraBin * camera, GstStructure * st,
- const GValue * orig_framerate)
-{
- const GValue *framerate = NULL;
- guint i, i_best, list_size;
- gint res, comparison;
-
- if (camera->night_mode) {
- GST_LOG_OBJECT (camera, "finding min framerate");
- comparison = GST_VALUE_LESS_THAN;
- } else {
- GST_LOG_OBJECT (camera, "finding max framerate");
- comparison = GST_VALUE_GREATER_THAN;
- }
-
- if (gst_structure_has_field (st, "framerate")) {
- framerate = gst_structure_get_value (st, "framerate");
- /* Handle framerate lists */
- if (GST_VALUE_HOLDS_LIST (framerate)) {
- list_size = gst_value_list_get_size (framerate);
- GST_LOG_OBJECT (camera, "finding framerate from list");
- for (i = 0, i_best = 0; i < list_size; i++) {
- res = gst_value_compare (gst_value_list_get_value (framerate, i),
- gst_value_list_get_value (framerate, i_best));
- if (comparison == res) {
- i_best = i;
- }
- }
- GST_LOG_OBJECT (camera, "found best framerate from index %d", i_best);
- framerate = gst_value_list_get_value (framerate, i_best);
- }
- /* Handle framerate ranges */
- if (GST_VALUE_HOLDS_FRACTION_RANGE (framerate)) {
- if (camera->night_mode) {
- GST_LOG_OBJECT (camera, "getting min framerate from range");
- framerate = gst_value_get_fraction_range_min (framerate);
- } else {
- GST_LOG_OBJECT (camera, "getting max framerate from range");
- framerate = gst_value_get_fraction_range_max (framerate);
- }
- }
- }
-
- /* Check if we found better framerate */
- if (orig_framerate && framerate) {
- res = gst_value_compare (orig_framerate, framerate);
- if (comparison == res) {
- GST_LOG_OBJECT (camera, "original framerate was the best");
- framerate = orig_framerate;
- }
- }
-
- return framerate;
-}
-
-/*
- * GObject callback functions implementation
- */
-
-static void
-gst_camerabin_base_init (gpointer gclass)
-{
- static GstElementDetails element_details = {
- "Camera Bin",
- "Generic/Bin/Camera",
- "Handle lot of features present in DSC",
- "Nokia Corporation <multimedia@maemo.org>\n"
- "Edgard Lima <edgard.lima@indt.org.br>"
- };
- GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
-
- gst_element_class_set_details (element_class, &element_details);
-}
-
-static void
-gst_camerabin_class_init (GstCameraBinClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBinClass *gstbin_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
- gstbin_class = GST_BIN_CLASS (klass);
-
- /* gobject */
-
- gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_camerabin_dispose);
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_camerabin_finalize);
-
- gobject_class->set_property = gst_camerabin_set_property;
- gobject_class->get_property = gst_camerabin_get_property;
-
- /**
- * GstCameraBin:filename:
- *
- * Set filename for the still image capturing or video capturing.
- */
-
- g_object_class_install_property (gobject_class, ARG_FILENAME,
- g_param_spec_string ("filename", "Filename",
- "Filename of the image or video to save", "", G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:mode:
- *
- * Set the mode of operation: still image capturing or video recording.
- * Setting the mode will create and destroy image bin or video bin elements
- * according to the mode. You can set this property at any time, changing
- * the mode will stop ongoing capture.
- */
-
- g_object_class_install_property (gobject_class, ARG_MODE,
- g_param_spec_enum ("mode", "Mode",
- "The capture mode (still image capture or video recording)",
- GST_TYPE_CAMERABIN_MODE, DEFAULT_MODE, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:mute:
- *
- * Mute audio in video recording mode.
- * Set this property only when #GstCameraBin is in READY, PAUSED or PLAYING.
- */
-
- g_object_class_install_property (gobject_class, ARG_MUTE,
- g_param_spec_boolean ("mute", "Mute",
- "True to mute the recording. False to record with audio",
- ARG_DEFAULT_MUTE, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:zoom:
- *
- * Set up the zoom applied to the frames.
- * Set this property only when #GstCameraBin is in READY, PAUSED or PLAYING.
- */
-
- g_object_class_install_property (gobject_class, ARG_ZOOM,
- g_param_spec_int ("zoom", "Zoom",
- "The zoom. 100 for 1x, 200 for 2x and so on",
- MIN_ZOOM, MAX_ZOOM, DEFAULT_ZOOM, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:imagepp:
- *
- * Set up an element to do image post processing.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
- g_object_class_install_property (gobject_class, ARG_IMAGE_POST,
- g_param_spec_object ("imagepp", "Image post processing element",
- "Image Post-Processing GStreamer element (default is NULL)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:imageenc:
- *
- * Set up an image encoder (for example, jpegenc or pngenc) element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_IMAGE_ENC,
- g_param_spec_object ("imageenc", "Image encoder",
- "Image encoder GStreamer element (default is jpegenc)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:videopp:
- *
- * Set up an element to do video post processing.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_VIDEO_POST,
- g_param_spec_object ("videopp", "Video post processing element",
- "Video post processing GStreamer element (default is NULL)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:videoenc:
- *
- * Set up a video encoder element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_VIDEO_ENC,
- g_param_spec_object ("videoenc", "Video encoder",
- "Video encoder GStreamer element (default is theoraenc)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:audioenc:
- *
- * Set up an audio encoder element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_AUDIO_ENC,
- g_param_spec_object ("audioenc", "Audio encoder",
- "Audio encoder GStreamer element (default is vorbisenc)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:videomux:
- *
- * Set up a video muxer element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_VIDEO_MUX,
- g_param_spec_object ("videomux", "Video muxer",
- "Video muxer GStreamer element (default is oggmux)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:vfsink:
- *
- * Set up a sink element to render frames in view finder.
- * By default "autovideosink" will be the sink element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_VF_SINK,
- g_param_spec_object ("vfsink", "View finder sink",
- "View finder sink GStreamer element (default is " DEFAULT_VIEW_SINK
- ")", GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:videosrc:
- *
- * Set up a video source element.
- * By default "v4l2src" will be the src element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_VIDEO_SRC,
- g_param_spec_object ("videosrc", "Video source element",
- "Video source GStreamer element (default is " DEFAULT_SRC_VID_SRC ")",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
- /**
- * GstCameraBin:audiosrc:
- *
- * Set up an audio source element.
- * By default "pulsesrc" will be the source element.
- * This property can only be set while #GstCameraBin is in NULL state.
- * The ownership of the element will be taken by #GstCameraBin.
- */
-
- g_object_class_install_property (gobject_class, ARG_AUDIO_SRC,
- g_param_spec_object ("audiosrc", "Audio source element",
- "Audio source GStreamer element (default is pulsesrc)",
- GST_TYPE_ELEMENT, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin:inputcaps:
- *
- * The allowed modes of operation of the video source. Have in mind that it
- * doesn't mean #GstCameraBin can operate in all those modes,
- * it depends also on the other elements in the pipeline. Remember to
- * gst_caps_unref after using it.
- */
-
- g_object_class_install_property (gobject_class, ARG_INPUT_CAPS,
- g_param_spec_boxed ("inputcaps", "Input caps",
- "The allowed modes of the video source operation",
- GST_TYPE_CAPS, G_PARAM_READABLE));
-
- /**
- * GstCameraBin:filter-caps:
- *
- * Filter video source element caps using this property.
- * This is an alternative to #GstCamerabin::user-res-fps action
- * signal that allows more fine grained control of video source.
- */
-
- g_object_class_install_property (gobject_class, ARG_FILTER_CAPS,
- g_param_spec_boxed ("filter-caps", "Filter caps",
- "Capsfilter caps used to control video source operation",
- GST_TYPE_CAPS, G_PARAM_READWRITE));
-
- /**
- * GstCameraBin::user-start:
- * @camera: the camera bin element
- *
- * Starts image capture or video recording depending on the Mode.
- * If there is a capture already going on, does nothing.
- * Resumes video recording if it has been paused.
- */
-
- camerabin_signals[USER_START_SIGNAL] =
- g_signal_new ("user-start",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GstCameraBinClass, user_start),
- NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
- /**
- * GstCameraBin::user-stop:
- * @camera: the camera bin element
- *
- * Stops still image preview, continuous image capture and video
- * recording and returns to the view finder mode.
- */
-
- camerabin_signals[USER_STOP_SIGNAL] =
- g_signal_new ("user-stop",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GstCameraBinClass, user_stop),
- NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
- /**
- * GstCameraBin::user-pause:
- * @camera: the camera bin element
- *
- * Pauses video recording or resumes paused video recording.
- * If in image mode or not recording, does nothing.
- */
-
- camerabin_signals[USER_PAUSE_SIGNAL] =
- g_signal_new ("user-pause",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GstCameraBinClass, user_pause),
- NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
-
- /**
- * GstCameraBin::user-res-fps:
- * @camera: the camera bin element
- * @width: number of horizontal pixels
- * @height: number of vertical pixels
- * @fps_n: frames per second numerator
- * @fps_d: frames per second denominator
- *
- * Changes the frame resolution and frames per second of the video source.
- * The application must be aware of the resolutions supported by the camera.
- * Supported resolutions and frame rates can be get using input-caps property.
- *
- * Setting @fps_n or @fps_d to 0 configures maximum framerate for the
- * given resolution, unless in night mode when minimum is configured.
- */
-
- camerabin_signals[USER_RES_FPS_SIGNAL] =
- g_signal_new ("user-res-fps",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GstCameraBinClass, user_res_fps),
- NULL, NULL, gst_camerabin_marshal_VOID__INT_INT_INT_INT, G_TYPE_NONE, 4,
- G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-
- /**
- * GstCameraBin::user-image-res:
- * @camera: the camera bin element
- * @width: number of horizontal pixels
- * @height: number of vertical pixels
- *
- * Changes the resolution used for still image capture.
- * Does not affect view finder mode and video recording.
- * Use this action signal in PAUSED or PLAYING state.
- */
-
- camerabin_signals[USER_IMAGE_RES_SIGNAL] =
- g_signal_new ("user-image-res",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GstCameraBinClass, user_image_res),
- NULL, NULL, gst_camerabin_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
- G_TYPE_INT, G_TYPE_INT);
-
- /**
- * GstCameraBin::img-done:
- * @camera: the camera bin element
- * @filename: the name of the file just saved
- *
- * Signal emited when the file has just been saved. To continue taking
- * pictures just update @filename and return TRUE, otherwise return FALSE.
- *
- * Don't call any #GstCameraBin method from this signal, if you do so there
- * will be a deadlock.
- */
-
- camerabin_signals[IMG_DONE_SIGNAL] =
- g_signal_new ("img-done", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstCameraBinClass, img_done),
- g_signal_accumulator_true_handled, NULL, gst_marshal_BOOLEAN__POINTER,
- G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
-
- klass->user_start = gst_camerabin_user_start;
- klass->user_stop = gst_camerabin_user_stop;
- klass->user_pause = gst_camerabin_user_pause;
- klass->user_res_fps = gst_camerabin_user_res_fps;
- klass->user_image_res = gst_camerabin_user_image_res;
-
- klass->img_done = gst_camerabin_default_signal_img_done;
-
- /* gstelement */
-
- gstelement_class->change_state =
- GST_DEBUG_FUNCPTR (gst_camerabin_change_state);
-
- /* gstbin */
- /* override handle_message to peek when video or image bin reaches eos */
- gstbin_class->handle_message =
- GST_DEBUG_FUNCPTR (gst_camerabin_handle_message_func);
-
-}
-
-/* initialize the new element
- * instantiate pads and add them to element
- * set functions
- * initialize structure
- */
-static void
-gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass)
-{
- /* GstElementClass *klass = GST_ELEMENT_GET_CLASS (camera); */
-
- camera->filename = g_string_new ("");
- camera->mode = DEFAULT_MODE;
- camera->num_img_buffers = 0;
- camera->stop_requested = FALSE;
- camera->paused = FALSE;
- camera->capturing = FALSE;
- camera->night_mode = FALSE;
-
- camera->width = DEFAULT_WIDTH;
- camera->height = DEFAULT_HEIGHT;
- camera->fps_n = DEFAULT_FPS_N;
- camera->fps_d = DEFAULT_FPS_D;
-
- camera->image_capture_caps = NULL;
- camera->view_finder_caps = NULL;
- camera->allowed_caps = NULL;
-
- camera->zoom = DEFAULT_ZOOM;
-
- /* concurrency control */
- camera->capture_mutex = g_mutex_new ();
- camera->cond = g_cond_new ();
-
- /* pad names for output and input selectors */
- camera->pad_src_view = NULL;
- camera->pad_view_src = NULL;
- camera->pad_src_img = NULL;
- camera->pad_view_img = NULL;
- camera->pad_src_vid = NULL;
- camera->pad_view_vid = NULL;
- camera->srcpad_zoom_filter = NULL;
-
- /* source elements */
- camera->src_vid_src = NULL;
- camera->src_filter = NULL;
- camera->src_zoom_crop = NULL;
- camera->src_zoom_scale = NULL;
- camera->src_zoom_filter = NULL;
- camera->src_out_sel = NULL;
-
- camera->user_vf_sink = NULL;
-
- /* image capture bin */
- camera->imgbin = g_object_new (GST_TYPE_CAMERABIN_IMAGE, NULL);
- gst_object_ref (camera->imgbin);
-
- /* video capture bin */
- camera->vidbin = g_object_new (GST_TYPE_CAMERABIN_VIDEO, NULL);
- gst_object_ref (camera->vidbin);
-
- camera->active_bin = NULL;
-
- /* view finder elements */
- camera->view_in_sel = NULL;
- camera->view_scale = NULL;
- camera->view_sink = NULL;
-}
-
-static void
-gst_camerabin_dispose (GObject * object)
-{
- GstCameraBin *camera;
-
- camera = GST_CAMERABIN (object);
-
- GST_DEBUG_OBJECT (camera, "disposing");
-
- gst_element_set_state (camera->imgbin, GST_STATE_NULL);
- gst_object_unref (camera->imgbin);
-
- gst_element_set_state (camera->vidbin, GST_STATE_NULL);
- gst_object_unref (camera->vidbin);
-
- camerabin_destroy_elements (camera);
-
- camerabin_dispose_elements (camera);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-gst_camerabin_finalize (GObject * object)
-{
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_camerabin_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstCameraBin *camera = GST_CAMERABIN (object);
-
- switch (prop_id) {
- case ARG_MUTE:
- gst_camerabin_video_set_mute (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_boolean (value));
- break;
- case ARG_ZOOM:
- g_atomic_int_set (&camera->zoom, g_value_get_int (value));
- gst_camerabin_setup_zoom (camera);
- break;
- case ARG_MODE:
- gst_camerabin_change_mode (camera, g_value_get_enum (value));
- break;
- case ARG_FILENAME:
- gst_camerabin_change_filename (camera, g_value_get_string (value));
- break;
- case ARG_VIDEO_POST:
- if (GST_STATE (camera->vidbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next video bin NULL to READY state change");
- }
- gst_camerabin_video_set_post (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_object (value));
- break;
- case ARG_VIDEO_ENC:
- if (GST_STATE (camera->vidbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next video bin NULL to READY state change");
- }
- gst_camerabin_video_set_video_enc (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_object (value));
- break;
- case ARG_AUDIO_ENC:
- if (GST_STATE (camera->vidbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next video bin NULL to READY state change");
- }
- gst_camerabin_video_set_audio_enc (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_object (value));
- break;
- case ARG_VIDEO_MUX:
- if (GST_STATE (camera->vidbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera->vidbin,
- "can't use set element until next video bin NULL to READY state change");
- }
- gst_camerabin_video_set_muxer (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_object (value));
- break;
- case ARG_IMAGE_POST:
- if (GST_STATE (camera->imgbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next image bin NULL to READY state change");
- }
- gst_camerabin_image_set_postproc (GST_CAMERABIN_IMAGE (camera->imgbin),
- g_value_get_object (value));
- break;
- case ARG_IMAGE_ENC:
- if (GST_STATE (camera->imgbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next image bin NULL to READY state change");
- }
- gst_camerabin_image_set_encoder (GST_CAMERABIN_IMAGE (camera->imgbin),
- g_value_get_object (value));
- break;
- case ARG_VF_SINK:
- if (GST_STATE (camera) != GST_STATE_NULL) {
- GST_ELEMENT_ERROR (camera, CORE, FAILED,
- ("camerabin must be in NULL state when setting the view finder element"),
- (NULL));
- } else {
- if (camera->user_vf_sink)
- gst_object_unref (camera->user_vf_sink);
- camera->user_vf_sink = g_value_get_object (value);
- gst_object_ref (camera->user_vf_sink);
- }
- break;
- case ARG_VIDEO_SRC:
- if (GST_STATE (camera) != GST_STATE_NULL) {
- GST_ELEMENT_ERROR (camera, CORE, FAILED,
- ("camerabin must be in NULL state when setting the video source element"),
- (NULL));
- } else {
- if (camera->user_vid_src)
- gst_object_unref (camera->user_vid_src);
- camera->user_vid_src = g_value_get_object (value);
- gst_object_ref (camera->user_vid_src);
- }
- break;
- case ARG_AUDIO_SRC:
- if (GST_STATE (camera->vidbin) != GST_STATE_NULL) {
- GST_WARNING_OBJECT (camera,
- "can't use set element until next video bin NULL to READY state change");
- }
- gst_camerabin_video_set_audio_src (GST_CAMERABIN_VIDEO (camera->vidbin),
- g_value_get_object (value));
- break;
- case ARG_FILTER_CAPS:
- GST_OBJECT_LOCK (camera);
- if (camera->view_finder_caps) {
- gst_caps_unref (camera->view_finder_caps);
- }
- camera->view_finder_caps = gst_caps_copy (gst_value_get_caps (value));
- GST_OBJECT_UNLOCK (camera);
- gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_camerabin_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec)
-{
- GstCameraBin *camera = GST_CAMERABIN (object);
-
- switch (prop_id) {
- case ARG_FILENAME:
- g_value_set_string (value, camera->filename->str);
- break;
- case ARG_MODE:
- g_value_set_enum (value, camera->mode);
- break;
- case ARG_MUTE:
- g_value_set_boolean (value,
- gst_camerabin_video_get_mute (GST_CAMERABIN_VIDEO (camera->vidbin)));
- break;
- case ARG_ZOOM:
- g_value_set_int (value, g_atomic_int_get (&camera->zoom));
- break;
- case ARG_IMAGE_POST:
- g_value_set_object (value,
- gst_camerabin_image_get_postproc (GST_CAMERABIN_IMAGE
- (camera->imgbin)));
- break;
- case ARG_IMAGE_ENC:
- g_value_set_object (value,
- gst_camerabin_image_get_encoder (GST_CAMERABIN_IMAGE
- (camera->imgbin)));
- break;
- case ARG_VIDEO_POST:
- g_value_set_object (value,
- gst_camerabin_video_get_post (GST_CAMERABIN_VIDEO (camera->vidbin)));
- break;
- case ARG_VIDEO_ENC:
- g_value_set_object (value,
- gst_camerabin_video_get_video_enc (GST_CAMERABIN_VIDEO
- (camera->vidbin)));
- break;
- case ARG_AUDIO_ENC:
- g_value_set_object (value,
- gst_camerabin_video_get_audio_enc (GST_CAMERABIN_VIDEO
- (camera->vidbin)));
- break;
- case ARG_VIDEO_MUX:
- g_value_set_object (value,
- gst_camerabin_video_get_muxer (GST_CAMERABIN_VIDEO (camera->vidbin)));
- break;
- case ARG_VF_SINK:
- g_value_set_object (value, camera->user_vf_sink);
- break;
- case ARG_VIDEO_SRC:
- g_value_set_object (value, camera->src_vid_src);
- break;
- case ARG_AUDIO_SRC:
- g_value_set_object (value,
- gst_camerabin_video_get_audio_src (GST_CAMERABIN_VIDEO
- (camera->vidbin)));
- break;
- case ARG_INPUT_CAPS:
- gst_value_set_caps (value, gst_camerabin_get_allowed_input_caps (camera));
- break;
- case ARG_FILTER_CAPS:
- gst_value_set_caps (value, camera->view_finder_caps);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-/*
- * GstElement functions implementation
- */
-
-static GstStateChangeReturn
-gst_camerabin_change_state (GstElement * element, GstStateChange transition)
-{
- GstCameraBin *camera = GST_CAMERABIN (element);
- GstStateChangeReturn ret;
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!camerabin_create_elements (camera)) {
- ret = GST_STATE_CHANGE_FAILURE;
- goto done;
- }
- /* Lock to control image and video bin state separately
- from view finder */
- gst_element_set_locked_state (camera->imgbin, TRUE);
- gst_element_set_locked_state (camera->vidbin, TRUE);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- camerabin_setup_src_elements (camera);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- /* If using autovideosink, set view finder sink properties
- now that actual sink has been created. */
- camerabin_setup_view_elements (camera);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- gst_element_set_locked_state (camera->imgbin, FALSE);
- gst_element_set_locked_state (camera->vidbin, FALSE);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- GST_LOG_OBJECT (camera, "PAUSED to READY");
- g_mutex_lock (camera->capture_mutex);
- if (camera->capturing) {
- GST_WARNING_OBJECT (camera, "was capturing when changing to READY");
- camera->capturing = FALSE;
- /* Reset capture and don't wait for capturing to finish properly.
- Proper capturing should have been finished before going to READY. */
- gst_camerabin_reset_to_view_finder (camera);
- g_cond_signal (camera->cond);
- }
- g_mutex_unlock (camera->capture_mutex);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- camerabin_destroy_elements (camera);
- break;
- default:
- break;
- }
-
-done:
-
- return ret;
-}
-
-/*
- * GstBin functions implementation
- */
-
-/* Peek eos messages but don't interfere with bin msg handling */
-static void
-gst_camerabin_handle_message_func (GstBin * bin, GstMessage * msg)
-{
- GstCameraBin *camera = GST_CAMERABIN (bin);
-
- switch (GST_MESSAGE_TYPE (msg)) {
- case GST_MESSAGE_EOS:
- if (GST_MESSAGE_SRC (msg) == GST_OBJECT (camera->vidbin)) {
- /* Video eos */
- GST_DEBUG_OBJECT (camera,
- "got video eos message, stopping video capture");
- g_mutex_lock (camera->capture_mutex);
- camera->capturing = FALSE;
- g_cond_signal (camera->cond);
- g_mutex_unlock (camera->capture_mutex);
- } else if (GST_MESSAGE_SRC (msg) == GST_OBJECT (camera->imgbin)) {
- /* Image eos */
- GST_DEBUG_OBJECT (camera, "got image eos message");
- /* Unblock pad to process next buffer */
- gst_pad_set_blocked_async (camera->pad_src_img, FALSE,
- (GstPadBlockCallback) image_pad_blocked, camera);
- }
- break;
- default:
- break;
- }
- GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
-}
-
-/*
- * Action signal function implementation
- */
-
-static void
-gst_camerabin_user_start (GstCameraBin * camera)
-{
-
- GST_INFO_OBJECT (camera, "starting capture");
- if (camera->paused) {
- gst_camerabin_user_pause (camera);
- return;
- }
-
- if (!camera->active_bin) {
- GST_INFO_OBJECT (camera, "mode not explicitly set by application");
- gst_camerabin_change_mode (camera, camera->mode);
- }
-
- if (g_str_equal (camera->filename->str, "")) {
- GST_ELEMENT_ERROR (camera, CORE, FAILED,
- ("set filename before starting capture"), (NULL));
- return;
- }
-
- g_mutex_lock (camera->capture_mutex);
- if (camera->capturing) {
- GST_WARNING_OBJECT (camera, "capturing \"%s\" ongoing, set new filename",
- camera->filename->str);
- g_mutex_unlock (camera->capture_mutex);
- return;
- }
- g_mutex_unlock (camera->capture_mutex);
-
- g_object_set (G_OBJECT (camera->active_bin), "filename",
- camera->filename->str, NULL);
-
- if (camera->active_bin == camera->imgbin) {
- gst_camerabin_start_image_capture (camera);
- } else if (camera->active_bin == camera->vidbin) {
- gst_camerabin_start_video_recording (camera);
- }
-}
-
-static void
-gst_camerabin_user_stop (GstCameraBin * camera)
-{
- GST_INFO_OBJECT (camera, "stopping %s capture",
- camera->mode ? "video" : "image");
- gst_camerabin_do_stop (camera);
- gst_camerabin_reset_to_view_finder (camera);
-}
-
-static void
-gst_camerabin_user_pause (GstCameraBin * camera)
-{
- if (camera->active_bin == camera->vidbin) {
- if (!camera->paused) {
- GST_INFO_OBJECT (camera, "pausing capture");
-
- /* Bring all camerabin elements to PAUSED */
- gst_element_set_locked_state (camera->vidbin, FALSE);
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PAUSED);
-
- /* Switch to view finder mode */
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE,
- "active-pad", camera->pad_src_view, NULL);
-
- /* Enable view finder mode in v4l2camsrc */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS
- (camera->src_vid_src), "capture-mode")) {
- g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 0, NULL);
- }
-
- /* Set view finder to PLAYING and leave videobin PAUSED */
- gst_element_set_locked_state (camera->vidbin, TRUE);
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING);
-
- camera->paused = TRUE;
- } else {
- GST_INFO_OBJECT (camera, "unpausing capture");
-
- /* Bring all camerabin elements to PAUSED */
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PAUSED);
-
- /* Switch to video recording mode */
- g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE,
- "active-pad", camera->pad_src_vid, NULL);
-
- /* Enable video recording mode in v4l2camsrc */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS
- (camera->src_vid_src), "capture-mode")) {
- g_object_set (G_OBJECT (camera->src_vid_src), "capture-mode", 2, NULL);
- }
-
- /* Bring all camerabin elements to PLAYING */
- gst_element_set_locked_state (camera->vidbin, FALSE);
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING);
- gst_element_set_locked_state (camera->vidbin, TRUE);
-
- camera->paused = FALSE;
- }
- GST_DEBUG_OBJECT (camera, "pause done");
- } else {
- GST_WARNING ("pausing in image capture mode disabled");
- }
-}
-
-static void
-gst_camerabin_user_res_fps (GstCameraBin * camera, gint width, gint height,
- gint fps_n, gint fps_d)
-{
- GstState state;
-
- GST_INFO_OBJECT (camera, "switching resolution to %dx%d and fps to %d/%d",
- width, height, fps_n, fps_d);
-
- state = GST_STATE (camera);
- gst_element_set_state (GST_ELEMENT (camera), GST_STATE_READY);
- camera->width = width;
- camera->height = height;
- camera->fps_n = fps_n;
- camera->fps_d = fps_d;
- gst_element_set_state (GST_ELEMENT (camera), state);
-}
-
-static void
-gst_camerabin_user_image_res (GstCameraBin * camera, gint width, gint height)
-{
- GstStructure *structure;
- GstCaps *new_caps = NULL;
- guint32 format = 0;
-
- g_return_if_fail (camera != NULL);
-
- if (width && height && camera->view_finder_caps) {
- /* Use view finder mode caps as a basis */
- structure = gst_caps_get_structure (camera->view_finder_caps, 0);
-
- /* Set new resolution for image capture */
- new_caps = gst_caps_new_simple (gst_structure_get_name (structure),
- "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
-
- /* Set format according to current videosrc format */
- format = get_srcpad_current_format (camera->src_vid_src);
- if (format) {
- gst_caps_set_simple (new_caps, "format", GST_TYPE_FOURCC, format, NULL);
- }
-
- /* Set allowed framerate for the resolution. */
- gst_camerabin_set_allowed_framerate (camera, new_caps);
-
- /* Reset the format to match with view finder mode caps */
- if (gst_structure_get_fourcc (structure, "format", &format)) {
- gst_caps_set_simple (new_caps, "format", GST_TYPE_FOURCC, format, NULL);
- }
- }
-
- GST_INFO_OBJECT (camera,
- "init filter caps for image capture %" GST_PTR_FORMAT, new_caps);
- gst_caps_replace (&camera->image_capture_caps, new_caps);
-}
-
-/* entry point to initialize the plug-in
- * initialize the plug-in itself
- * register the element factories and pad templates
- * register the features
- */
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- GST_DEBUG_CATEGORY_INIT (gst_camerabin_debug, "camerabin", 0, "CameraBin");
-
- return gst_element_register (plugin, "camerabin",
- GST_RANK_NONE, GST_TYPE_CAMERABIN);
-}
-
-/* this is the structure that gstreamer looks for to register plugins
- */
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "camerabin",
- "High level api for DC (Digital Camera) application",
- plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
--- a/gst_plugins_good/gst/camerabin/gstcamerabin.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __GST_CAMERABIN_H__
-#define __GST_CAMERABIN_H__
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <gst/gstbin.h>
-#include <gst/interfaces/photography.h>
-
-#include "camerabinimage.h"
-#include "camerabinvideo.h"
-
-G_BEGIN_DECLS
-
-/* #defines don't like whitespacey bits */
-#define GST_TYPE_CAMERABIN \
- (gst_camerabin_get_type())
-#define GST_CAMERABIN(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN,GstCameraBin))
-#define GST_CAMERABIN_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN,GstCameraBinClass))
-#define GST_IS_CAMERABIN(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN))
-#define GST_IS_CAMERABIN_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN))
-
-typedef struct _GstCameraBin GstCameraBin;
-typedef struct _GstCameraBinClass GstCameraBinClass;
-
-/**
- * GstCameraBin:
- *
- * The opaque #GstCameraBin structure.
- */
-
-struct _GstCameraBin
-{
- GstPipeline parent;
-
- /* private */
- GString *filename;
- gint mode; /* MODE_IMAGE or MODE_VIDEO */
- guint num_img_buffers; /* no of image buffers captured */
- gboolean stop_requested; /* TRUE if capturing stop needed */
- gboolean paused; /* TRUE if capturing paused */
-
- /* resolution and frames per second of image captured by v4l2 device */
- gint width;
- gint height;
- gint fps_n;
- gint fps_d;
-
- /* Caps applied to capsfilters when taking still image */
- GstCaps *image_capture_caps;
-
- /* Caps applied to capsfilters when in view finder mode */
- GstCaps *view_finder_caps;
-
- /* Caps that videosrc supports */
- GstCaps *allowed_caps;
-
- /* The digital zoom (from 100% to 1000%) */
- gint zoom;
-
- /* concurrency control */
- GMutex *capture_mutex;
- GCond *cond;
- gboolean capturing;
-
- /* pad names for output and input selectors */
- GstPad *pad_src_view;
- GstPad *pad_view_src;
- GstPad *pad_src_img;
- GstPad *pad_view_img;
- GstPad *pad_src_vid;
- GstPad *pad_view_vid;
-
- GstPad *srcpad_zoom_filter;
-
- GstElement *imgbin; /* bin that holds image capturing elements */
- GstElement *vidbin; /* bin that holds video capturing elements */
- GstElement *active_bin; /* image or video bin that is currently in use */
-
- /* source elements */
- GstElement *src_vid_src;
- GstElement *src_filter;
- GstElement *src_zoom_crop;
- GstElement *src_zoom_scale;
- GstElement *src_zoom_filter;
- GstElement *src_out_sel;
-
- /* view finder elements */
- GstElement *view_in_sel;
- GstElement *view_scale;
- GstElement *view_sink;
-
- /* User configurable elements */
- GstElement *user_vid_src;
- GstElement *user_vf_sink;
-
- /* Night mode handling */
- gboolean night_mode;
- gint pre_night_fps_n;
- gint pre_night_fps_d;
-};
-
-/**
- * GstCameraBinClass:
- *
- * The #GstCameraBin class structure.
- */
-struct _GstCameraBinClass
-{
- GstPipelineClass parent_class;
-
- /* action signals */
-
- void (*user_start) (GstCameraBin * camera);
- void (*user_stop) (GstCameraBin * camera);
- void (*user_pause) (GstCameraBin * camera);
- void (*user_res_fps) (GstCameraBin * camera, gint width, gint height,
- gint fps_n, gint fps_d);
- void (*user_image_res) (GstCameraBin * camera, gint width, gint height);
-
- /* signals (callback) */
-
- gboolean (*img_done) (GstCameraBin * camera, GString * filename);
-};
-
-/**
- * GstCameraBinMode:
- * @MODE_IMAGE: image capture
- * @MODE_VIDEO: video capture
- *
- * Capture mode to use.
- */
-typedef enum
-{
- MODE_IMAGE = 0,
- MODE_VIDEO
-} GstCameraBinMode;
-
-#ifdef __SYMBIAN32__
-IMPORT_C
-#endif
-GType gst_camerabin_get_type (void);
-
-G_END_DECLS
-
-#endif /* #ifndef __GST_CAMERABIN_H__ */
--- a/gst_plugins_good/gst/camerabin/gstcamerabincolorbalance.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/*
- * Includes
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstcamerabincolorbalance.h"
-#include "gstcamerabin.h"
-
-/*
- * static functions implementation
- */
-
-static const GList *
-gst_camerabin_color_balance_list_channels (GstColorBalance * cb)
-{
- if (cb && GST_CAMERABIN (cb)->src_vid_src) {
- GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
- return gst_color_balance_list_channels (cbl);
- } else {
- return NULL;
- }
-}
-
-static void
-gst_camerabin_color_balance_set_value (GstColorBalance * cb,
- GstColorBalanceChannel * channel, gint value)
-{
- if (cb && GST_CAMERABIN (cb)->src_vid_src) {
- GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
- gst_color_balance_set_value (cbl, channel, value);
- }
-}
-
-static gint
-gst_camerabin_color_balance_get_value (GstColorBalance * cb,
- GstColorBalanceChannel * channel)
-{
- if (cb && GST_CAMERABIN (cb)->src_vid_src) {
- GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
- return gst_color_balance_get_value (cbl, channel);
- } else {
- return 0;
- }
-}
-
-/*
- * extern functions implementation
- */
-
-void
-gst_camerabin_color_balance_init (GstColorBalanceClass * iface)
-{
- /* FIXME: to get the same type as v4l2src */
- GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
- iface->list_channels = gst_camerabin_color_balance_list_channels;
- iface->set_value = gst_camerabin_color_balance_set_value;
- iface->get_value = gst_camerabin_color_balance_get_value;
-}
--- a/gst_plugins_good/gst/camerabin/gstcamerabincolorbalance.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __GST_CAMERA_COLOR_BALANCE_H__
-#define __GST_CAMERA_COLOR_BALANCE_H__
-
-#include <gst/interfaces/colorbalance.h>
-
-extern void gst_camerabin_color_balance_init (GstColorBalanceClass * iface);
-
-#endif /* #ifndef __GST_CAMERA_COLOR_BALANCE_H__ */
--- a/gst_plugins_good/gst/camerabin/gstcamerabinphotography.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * Photography interface implementation for camerabin.
- *
- * 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 "gstcamerabinphotography.h"
-#include "gstcamerabin.h"
-
-GST_DEBUG_CATEGORY_STATIC (camerabinphoto_debug);
-#define GST_CAT_DEFAULT camerabinphoto_debug
-
-#define PHOTOGRAPHY_IS_OK(photo_elem) (GST_IS_ELEMENT (photo_elem) && \
- gst_element_implements_interface (photo_elem, GST_TYPE_PHOTOGRAPHY))
-
-#define GST_PHOTOGRAPHY_IMPL_TEMPLATE(function_name, param_type) \
-static gboolean \
-gst_camerabin_set_ ## function_name (GstPhotography *photo, param_type param) \
-{ \
- GstCameraBin *camera; \
- gboolean ret = FALSE; \
- g_return_val_if_fail (photo != NULL, FALSE); \
- camera = GST_CAMERABIN (photo); \
- if (PHOTOGRAPHY_IS_OK (camera->src_vid_src)) { \
- ret = gst_photography_set_ ## function_name (GST_PHOTOGRAPHY (camera->src_vid_src), param); \
- } \
- return ret; \
-} \
-static gboolean \
-gst_camerabin_get_ ## function_name (GstPhotography *photo, param_type * param) \
-{ \
- GstCameraBin *camera; \
- gboolean ret = FALSE; \
- g_return_val_if_fail (photo != NULL, FALSE); \
- camera = GST_CAMERABIN (photo); \
- if (PHOTOGRAPHY_IS_OK (camera->src_vid_src)) { \
- ret = gst_photography_get_ ## function_name (GST_PHOTOGRAPHY (camera->src_vid_src), param); \
- } \
- return ret; \
-}
-
-GST_PHOTOGRAPHY_IMPL_TEMPLATE (ev_compensation, gfloat);
-GST_PHOTOGRAPHY_IMPL_TEMPLATE (iso_speed, guint);
-GST_PHOTOGRAPHY_IMPL_TEMPLATE (white_balance_mode, GstWhiteBalanceMode);
-GST_PHOTOGRAPHY_IMPL_TEMPLATE (colour_tone_mode, GstColourToneMode);
-GST_PHOTOGRAPHY_IMPL_TEMPLATE (flash_mode, GstFlashMode);
-
-static gboolean
-gst_camerabin_set_zoom (GstPhotography * photo, gfloat zoom)
-{
- GstCameraBin *camera;
-
- g_return_val_if_fail (photo != NULL, FALSE);
-
- camera = GST_CAMERABIN (photo);
-
- /* camerabin can zoom by itself */
- g_object_set (camera, "zoom", (gint) (CLAMP (zoom, 1.0, 10.0) * 100), NULL);
-
- return TRUE;
-}
-
-static gboolean
-gst_camerabin_get_zoom (GstPhotography * photo, gfloat * zoom)
-{
- GstCameraBin *camera;
- gint cb_zoom = 0;
-
- g_return_val_if_fail (photo != NULL, FALSE);
-
- camera = GST_CAMERABIN (photo);
-
- g_object_get (camera, "zoom", &cb_zoom, NULL);
- *zoom = (gfloat) (cb_zoom / 100.0);
-
- return TRUE;
-}
-
-static gboolean
-gst_camerabin_set_scene_mode (GstPhotography * photo, GstSceneMode scene_mode)
-{
- GstCameraBin *camera;
- gboolean ret = FALSE;
-
- g_return_val_if_fail (photo != NULL, FALSE);
-
- camera = GST_CAMERABIN (photo);
-
- if (scene_mode == GST_PHOTOGRAPHY_SCENE_MODE_NIGHT) {
- GST_DEBUG ("enabling night mode, lowering fps");
- /* Make camerabin select the lowest allowed frame rate */
- camera->night_mode = TRUE;
- /* Remember frame rate before setting night mode */
- camera->pre_night_fps_n = camera->fps_n;
- camera->pre_night_fps_d = camera->fps_d;
- g_signal_emit_by_name (camera, "user-res-fps", camera->width,
- camera->height, 0, 0, 0);
- } else {
- if (camera->night_mode) {
- GST_DEBUG ("disabling night mode, restoring fps to %d/%d",
- camera->pre_night_fps_n, camera->pre_night_fps_d);
- camera->night_mode = FALSE;
- g_signal_emit_by_name (camera, "user-res-fps", camera->width,
- camera->height, camera->pre_night_fps_n, camera->pre_night_fps_d, 0);
- }
- }
-
- if (PHOTOGRAPHY_IS_OK (camera->src_vid_src)) {
- ret = gst_photography_set_scene_mode (GST_PHOTOGRAPHY (camera->src_vid_src),
- scene_mode);
- }
- return ret;
-}
-
-static gboolean
-gst_camerabin_get_scene_mode (GstPhotography * photo, GstSceneMode * scene_mode)
-{
- GstCameraBin *camera;
- gboolean ret = FALSE;
-
- g_return_val_if_fail (photo != NULL, FALSE);
-
- camera = GST_CAMERABIN (photo);
-
- if (PHOTOGRAPHY_IS_OK (camera->src_vid_src)) {
- ret = gst_photography_get_scene_mode (GST_PHOTOGRAPHY (camera->src_vid_src),
- scene_mode);
- }
- return ret;
-}
-
-static GstPhotoCaps
-gst_camerabin_get_capabilities (GstPhotography * photo)
-{
- GstCameraBin *camera;
- /* camerabin can zoom by itself */
- GstPhotoCaps pcaps = GST_PHOTOGRAPHY_CAPS_ZOOM;
-
- g_return_val_if_fail (photo != NULL, FALSE);
-
- camera = GST_CAMERABIN (photo);
-
- if (GST_IS_ELEMENT (camera->src_vid_src) &&
- gst_element_implements_interface (camera->src_vid_src,
- GST_TYPE_PHOTOGRAPHY)) {
- GstPhotography *p2 = GST_PHOTOGRAPHY (camera->src_vid_src);
- pcaps |= gst_photography_get_capabilities (p2);
- }
-
- return pcaps;
-}
-
-static void
-gst_camerabin_set_autofocus (GstPhotography * photo, gboolean on)
-{
- GstCameraBin *camera;
-
- g_return_if_fail (photo != NULL);
-
- camera = GST_CAMERABIN (photo);
-
- GST_DEBUG_OBJECT (camera, "setting autofocus %s", on ? "ON" : "OFF");
-
- if (PHOTOGRAPHY_IS_OK (camera->src_vid_src)) {
- gst_photography_set_autofocus (GST_PHOTOGRAPHY (camera->src_vid_src), on);
- }
-}
-
-
-void
-gst_camerabin_photography_init (GstPhotographyInterface * iface)
-{
- GST_DEBUG_CATEGORY_INIT (camerabinphoto_debug, "camerabinphoto", 0,
- "Camerabin photography interface debugging");
-
- GST_INFO ("initing");
-
- iface->set_ev_compensation = gst_camerabin_set_ev_compensation;
- iface->get_ev_compensation = gst_camerabin_get_ev_compensation;
-
- iface->set_iso_speed = gst_camerabin_set_iso_speed;
- iface->get_iso_speed = gst_camerabin_get_iso_speed;
-
- iface->set_white_balance_mode = gst_camerabin_set_white_balance_mode;
- iface->get_white_balance_mode = gst_camerabin_get_white_balance_mode;
-
- iface->set_colour_tone_mode = gst_camerabin_set_colour_tone_mode;
- iface->get_colour_tone_mode = gst_camerabin_get_colour_tone_mode;
-
- iface->set_scene_mode = gst_camerabin_set_scene_mode;
- iface->get_scene_mode = gst_camerabin_get_scene_mode;
-
- iface->set_flash_mode = gst_camerabin_set_flash_mode;
- iface->get_flash_mode = gst_camerabin_get_flash_mode;
-
- iface->set_zoom = gst_camerabin_set_zoom;
- iface->get_zoom = gst_camerabin_get_zoom;
-
- iface->get_capabilities = gst_camerabin_get_capabilities;
-
- iface->set_autofocus = gst_camerabin_set_autofocus;
-}
--- a/gst_plugins_good/gst/camerabin/gstcamerabinphotography.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * Photography interface implementation for camerabin
- *
- * 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 __GST_CAMERABIN_PHOTOGRAPHY_H__
-#define __GST_CAMERABIN_PHOTOGRAPHY_H__
-
-#include <gst/interfaces/photography.h>
-
-void gst_camerabin_photography_init (GstPhotographyInterface * iface);
-
-#endif /* #ifndef __GST_CAMERABIN_PHOTOGRAPHY_H__ */
--- a/gst_plugins_good/gst/camerabin/gstcamerabinxoverlay.c Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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.
- */
-
-/*
- * Includes
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "gstcamerabinxoverlay.h"
-#include "gstcamerabin.h"
-
-/*
- * static functions implementation
- */
-
-static void
-gst_camerabin_expose (GstXOverlay * overlay)
-{
- if (overlay && GST_CAMERABIN (overlay)->view_sink) {
- GstXOverlay *xoverlay = GST_X_OVERLAY (GST_CAMERABIN (overlay)->view_sink);
- gst_x_overlay_expose (xoverlay);
- }
-}
-
-static void
-gst_camerabin_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id)
-{
- if (overlay && GST_CAMERABIN (overlay)->view_sink) {
- GstXOverlay *xoverlay = GST_X_OVERLAY (GST_CAMERABIN (overlay)->view_sink);
- gst_x_overlay_set_xwindow_id (xoverlay, xwindow_id);
- }
-}
-
-static void
-gst_camerabin_set_event_handling (GstXOverlay * overlay, gboolean handle_events)
-{
- if (overlay && GST_CAMERABIN (overlay)->view_sink) {
- GstXOverlay *xoverlay = GST_X_OVERLAY (GST_CAMERABIN (overlay)->view_sink);
- gst_x_overlay_handle_events (xoverlay, handle_events);
- }
-}
-
-/*
- * extern functions implementation
- */
-
-void
-gst_camerabin_xoverlay_init (GstXOverlayClass * iface)
-{
- iface->set_xwindow_id = gst_camerabin_set_xwindow_id;
- iface->expose = gst_camerabin_expose;
- iface->handle_events = gst_camerabin_set_event_handling;
-}
--- a/gst_plugins_good/gst/camerabin/gstcamerabinxoverlay.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * GStreamer
- * Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
- *
- * 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 __GST_CAMERAXOVERLAY_H__
-#define __GST_CAMERAXOVERLAY_H__
-
-#include <gst/interfaces/xoverlay.h>
-
-extern void gst_camerabin_xoverlay_init (GstXOverlayClass * iface);
-
-#endif /* #ifndef __GST_CAMERAXOVERLAY_H__ */
--- a/gst_plugins_symbian/gst/devsound/gstdevsoundsrc.c Fri May 28 18:11:17 2010 -0500
+++ b/gst_plugins_symbian/gst/devsound/gstdevsoundsrc.c Fri Jun 25 17:18:46 2010 -0500
@@ -394,7 +394,7 @@
devsoundsrc->handle=NULL;
devsoundsrc->preference = 0; //default=>EMdaPriorityPreferenceNone;
devsoundsrc->priority = 0; //default=>EMdaPriorityNormal;
- devsoundsrc->firstimecreatecalled = 0;
+ devsoundsrc->firstTimeInit = kUnInitialized;
// pthread_mutex_init(&create_mutex1, NULL);
// pthread_cond_init(&create_condition1, NULL);
//gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "gst_devsound_src_init EXIT ",NULL);
@@ -500,7 +500,6 @@
pthread_mutex_unlock(&(create_mutex1));
// TODO obtain mutex here
consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
- devsoundsrc->firstimecreatecalled = 0;
pthread_exit(NULL);
}
break;
@@ -772,6 +771,7 @@
g_free(src->device);
src->device = NULL;
+ src->firstTimeInit = kUnInitialized;
//gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) src, "gst_devsound_src_stop EXIT ");
return TRUE;
}
@@ -882,8 +882,14 @@
GST_OBJECT_UNLOCK(dsrc);
//gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFTER POP in CREATE ",NULL);
if(!popBuffer)
- {
- return GST_FLOW_UNEXPECTED;
+ {
+ return GST_FLOW_UNEXPECTED;
+ }
+ if(dsrc->firstTimeInit != kPlayed)
+ {
+ dsrc->prevbuffersize = gst_base_src_get_blocksize(src);
+ gst_base_src_set_blocksize (src, GST_BUFFER_SIZE(popBuffer));
+ (*buf)->size = GST_BUFFER_SIZE(popBuffer);
}
// copy the data from the popped buffer based on how much of the incoming
//buffer size is left to fill. we might have filled the fresh buffer somewhat
@@ -914,12 +920,19 @@
popBuffer = NULL;
}
}
- if( dsrc->firstimecreatecalled < 2 )
- {/// nitin changes
- ++dsrc->firstimecreatecalled;
- return GST_FLOW_OK;
+ if (dsrc->firstTimeInit == kPlayBufferPreRoll)
+ {
+ gst_base_src_set_blocksize (src, dsrc->prevbuffersize);
+ dsrc->firstTimeInit = kPlayed;
+ return GST_FLOW_OK;
}
- }
+
+ if (dsrc->firstTimeInit == kPausedToPlaying)
+ {
+ dsrc->firstTimeInit = kPlayBufferPreRoll;
+ return GST_FLOW_OK;
+ }
+ }
//gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "gst_devsound_src_create EXIT ",NULL);
return GST_FLOW_OK;
}
@@ -930,10 +943,12 @@
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstDevsoundSrc *src= GST_DEVSOUND_SRC (element);
-
+
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ if (src->firstTimeInit != kPlayed)
+ src->firstTimeInit = kPausedToPlaying;
if(cmd == PAUSE)
{
cmd = RESUME;
--- a/gst_plugins_symbian/gst/devsound/gstdevsoundsrc.h Fri May 28 18:11:17 2010 -0500
+++ b/gst_plugins_symbian/gst/devsound/gstdevsoundsrc.h Fri Jun 25 17:18:46 2010 -0500
@@ -54,6 +54,13 @@
gboolean priorityupdate;
};
+typedef enum
+{
+ kUnInitialized = -1,
+ kPausedToPlaying,
+ kPlayBufferPreRoll,
+ kPlayed
+} ;
struct _GstDevsoundSrc {
GstPushSrc src;
@@ -86,8 +93,8 @@
gboolean g729vadmode;
gint ilbcencodemode;
gboolean ilbcvadmode;
- gint firstimecreatecalled;
-
+ gint firstTimeInit;
+ guint prevbuffersize;
};
--- a/gstreamer_core/group/bld.inf Fri May 28 18:11:17 2010 -0500
+++ b/gstreamer_core/group/bld.inf Fri Jun 25 17:18:46 2010 -0500
@@ -25,93 +25,93 @@
DEFAULT
PRJ_EXPORTS
-../gst/glib-compat.h /epoc32/include/platform/mw/gstreamer/gst/glib-compat.h
-../gst/gstbin.h /epoc32/include/platform/mw/gstreamer/gst/gstbin.h
-../gst/gstbuffer.h /epoc32/include/platform/mw/gstreamer/gst/gstbuffer.h
-../gst/gstbus.h /epoc32/include/platform/mw/gstreamer/gst/gstbus.h
-../gst/gstcaps.h /epoc32/include/platform/mw/gstreamer/gst/gstcaps.h
-../gst/gstchildproxy.h /epoc32/include/platform/mw/gstreamer/gst/gstchildproxy.h
-../gst/gstclock.h /epoc32/include/platform/mw/gstreamer/gst/gstclock.h
-../gst/gstcompat.h /epoc32/include/platform/mw/gstreamer/gst/gstcompat.h
-../gst/gstconfig.h /epoc32/include/platform/mw/gstreamer/gst/gstconfig.h
-../gst/gstelementfactory.h /epoc32/include/platform/mw/gstreamer/gst/gstelementfactory.h
-../gst/gstelement.h /epoc32/include/platform/mw/gstreamer/gst/gstelement.h
-../gst/gstenumtypes.h /epoc32/include/platform/mw/gstreamer/gst/gstenumtypes.h
-../gst/gsterror.h /epoc32/include/platform/mw/gstreamer/gst/gsterror.h
-../gst/gstevent.h /epoc32/include/platform/mw/gstreamer/gst/gstevent.h
-../gst/gstfilter.h /epoc32/include/platform/mw/gstreamer/gst/gstfilter.h
-../gst/gstformat.h /epoc32/include/platform/mw/gstreamer/gst/gstformat.h
-../gst/gstghostpad.h /epoc32/include/platform/mw/gstreamer/gst/gstghostpad.h
-../gst/gst.h /epoc32/include/platform/mw/gstreamer/gst/gst.h
-../gst/gstindexfactory.h /epoc32/include/platform/mw/gstreamer/gst/gstindexfactory.h
-../gst/gstindex.h /epoc32/include/platform/mw/gstreamer/gst/gstindex.h
-//../gst/gst_private.h /epoc32/include/platform/mw/gstreamer/gst/gst_private.h
-//../gst/gst-i18n-lib.h /epoc32/include/platform/mw/gstreamer/gst/gst-i18n-lib.h
-../gst/gstinfo.h /epoc32/include/platform/mw/gstreamer/gst/gstinfo.h
-../gst/gstinterface.h /epoc32/include/platform/mw/gstreamer/gst/gstinterface.h
-../gst/gstiterator.h /epoc32/include/platform/mw/gstreamer/gst/gstiterator.h
-../gst/gstmacros.h /epoc32/include/platform/mw/gstreamer/gst/gstmacros.h
-../gst/gstmarshal.h /epoc32/include/platform/mw/gstreamer/gst/gstmarshal.h
-../gst/gstmessage.h /epoc32/include/platform/mw/gstreamer/gst/gstmessage.h
-../gst/gstminiobject.h /epoc32/include/platform/mw/gstreamer/gst/gstminiobject.h
-../gst/gstobject.h /epoc32/include/platform/mw/gstreamer/gst/gstobject.h
-../gst/gstpad.h /epoc32/include/platform/mw/gstreamer/gst/gstpad.h
-../gst/gstpadtemplate.h /epoc32/include/platform/mw/gstreamer/gst/gstpadtemplate.h
-../gst/gstparse.h /epoc32/include/platform/mw/gstreamer/gst/gstparse.h
-../gst/gstpipeline.h /epoc32/include/platform/mw/gstreamer/gst/gstpipeline.h
-../gst/gstpluginfeature.h /epoc32/include/platform/mw/gstreamer/gst/gstpluginfeature.h
-../gst/gstplugin.h /epoc32/include/platform/mw/gstreamer/gst/gstplugin.h
-../gst/gstquery.h /epoc32/include/platform/mw/gstreamer/gst/gstquery.h
-../gst/gstregistry.h /epoc32/include/platform/mw/gstreamer/gst/gstregistry.h
-../gst/gstsegment.h /epoc32/include/platform/mw/gstreamer/gst/gstsegment.h
-../gst/gststructure.h /epoc32/include/platform/mw/gstreamer/gst/gststructure.h
-../gst/gstsystemclock.h /epoc32/include/platform/mw/gstreamer/gst/gstsystemclock.h
-../gst/gsttaglist.h /epoc32/include/platform/mw/gstreamer/gst/gsttaglist.h
-../gst/gsttagsetter.h /epoc32/include/platform/mw/gstreamer/gst/gsttagsetter.h
-../gst/gsttask.h /epoc32/include/platform/mw/gstreamer/gst/gsttask.h
-../gst/gsttrace.h /epoc32/include/platform/mw/gstreamer/gst/gsttrace.h
-../gst/gsttypefindfactory.h /epoc32/include/platform/mw/gstreamer/gst/gsttypefindfactory.h
-../gst/gsttypefind.h /epoc32/include/platform/mw/gstreamer/gst/gsttypefind.h
-../gst/gsturi.h /epoc32/include/platform/mw/gstreamer/gst/gsturi.h
-../gst/gstutils.h /epoc32/include/platform/mw/gstreamer/gst/gstutils.h
-../gst/gstvalue.h /epoc32/include/platform/mw/gstreamer/gst/gstvalue.h
-../gst/gstversion.h /epoc32/include/platform/mw/gstreamer/gst/gstversion.h
-../gst/gstxml.h /epoc32/include/platform/mw/gstreamer/gst/gstxml.h
-../gst/gst_global.h /epoc32/include/platform/mw/gstreamer/gst/gst_global.h
+../gst/glib-compat.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/glib-compat.h)
+../gst/gstbin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstbin.h)
+../gst/gstbuffer.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstbuffer.h)
+../gst/gstbus.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstbus.h)
+../gst/gstcaps.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstcaps.h)
+../gst/gstchildproxy.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstchildproxy.h)
+../gst/gstclock.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstclock.h)
+../gst/gstcompat.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstcompat.h)
+../gst/gstconfig.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstconfig.h)
+../gst/gstelementfactory.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstelementfactory.h)
+../gst/gstelement.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstelement.h)
+../gst/gstenumtypes.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstenumtypes.h )
+../gst/gsterror.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsterror.h )
+../gst/gstevent.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstevent.h )
+../gst/gstfilter.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstfilter.h )
+../gst/gstformat.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstformat.h )
+../gst/gstghostpad.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstghostpad.h )
+../gst/gst.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gst.h )
+../gst/gstindexfactory.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstindexfactory.h )
+../gst/gstindex.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstindex.h )
+//../gst/gst_private.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gst_private.h )
+//../gst/gst-i18n-lib.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gst-i18n-lib.h )
+../gst/gstinfo.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstinfo.h )
+../gst/gstinterface.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstinterface.h )
+../gst/gstiterator.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstiterator.h )
+../gst/gstmacros.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstmacros.h )
+../gst/gstmarshal.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstmarshal.h )
+../gst/gstmessage.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstmessage.h )
+../gst/gstminiobject.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstminiobject.h )
+../gst/gstobject.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstobject.h )
+../gst/gstpad.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpad.h )
+../gst/gstpadtemplate.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpadtemplate.h )
+../gst/gstparse.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstparse.h )
+../gst/gstpipeline.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpipeline.h )
+../gst/gstpluginfeature.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpluginfeature.h )
+../gst/gstplugin.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstplugin.h )
+../gst/gstquery.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstquery.h )
+../gst/gstregistry.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstregistry.h )
+../gst/gstsegment.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstsegment.h )
+../gst/gststructure.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gststructure.h )
+../gst/gstsystemclock.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstsystemclock.h )
+../gst/gsttaglist.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttaglist.h )
+../gst/gsttagsetter.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttagsetter.h )
+../gst/gsttask.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttask.h )
+../gst/gsttrace.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttrace.h )
+../gst/gsttypefindfactory.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttypefindfactory.h )
+../gst/gsttypefind.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttypefind.h )
+../gst/gsturi.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsturi.h )
+../gst/gstutils.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstutils.h )
+../gst/gstvalue.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstvalue.h )
+../gst/gstversion.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstversion.h )
+../gst/gstxml.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstxml.h )
+../gst/gst_global.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gst_global.h )
-../gst/gstdebugutils.h /epoc32/include/platform/mw/gstreamer/gst/gstdebugutils.h
-../gst/gstparamspecs.h /epoc32/include/platform/mw/gstreamer/gst/gstparamspecs.h
-../gst/gstpoll.h /epoc32/include/platform/mw/gstreamer/gst/gstpoll.h
-../gst/gstregistrybinary.h /epoc32/include/platform/mw/gstreamer/gst/gstregistrybinary.h
-../gst/gstpreset.h /epoc32/include/platform/mw/gstreamer/gst/gstpreset.h
-../gst/gstbufferlist.h /epoc32/include/platform/mw/gstreamer/gst/gstbufferlist.h
-../gst/gsttaskpool.h /epoc32/include/platform/mw/gstreamer/gst/gsttaskpool.h
+../gst/gstdebugutils.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstdebugutils.h )
+../gst/gstparamspecs.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstparamspecs.h )
+../gst/gstpoll.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpoll.h )
+../gst/gstregistrybinary.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstregistrybinary.h )
+../gst/gstpreset.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstpreset.h )
+../gst/gstbufferlist.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gstbufferlist.h )
+../gst/gsttaskpool.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/gsttaskpool.h )
//libs
//base
-../libs/gst/base/gstadapter.h /epoc32/include/platform/mw/gstreamer/gst/base/gstadapter.h
-../libs/gst/base/gstbasesink.h /epoc32/include/platform/mw/gstreamer/gst/base/gstbasesink.h
-../libs/gst/base/gstbasesrc.h /epoc32/include/platform/mw/gstreamer/gst/base/gstbasesrc.h
-../libs/gst/base/gstbasetransform.h /epoc32/include/platform/mw/gstreamer/gst/base/gstbasetransform.h
-../libs/gst/base/gstcollectpads.h /epoc32/include/platform/mw/gstreamer/gst/base/gstcollectpads.h
-../libs/gst/base/gstpushsrc.h /epoc32/include/platform/mw/gstreamer/gst/base/gstpushsrc.h
-../libs/gst/base/gsttypefindhelper.h /epoc32/include/platform/mw/gstreamer/gst/base/gsttypefindhelper.h
-../libs/gst/base/gstdataqueue.h /epoc32/include/platform/mw/gstreamer/gst/base/gstdataqueue.h
+../libs/gst/base/gstadapter.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstadapter.h )
+../libs/gst/base/gstbasesink.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstbasesink.h )
+../libs/gst/base/gstbasesrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstbasesrc.h )
+../libs/gst/base/gstbasetransform.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstbasetransform.h )
+../libs/gst/base/gstcollectpads.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstcollectpads.h )
+../libs/gst/base/gstpushsrc.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstpushsrc.h )
+../libs/gst/base/gsttypefindhelper.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gsttypefindhelper.h )
+../libs/gst/base/gstdataqueue.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/base/gstdataqueue.h )
//controller rj
-../libs/gst/controller/gstcontroller.h /epoc32/include/platform/mw/gstreamer/gst/controller/gstcontroller.h
-../libs/gst/controller/gstcontrolsource.h /epoc32/include/platform/mw/gstreamer/gst/controller/gstcontrolsource.h
-../libs/gst/controller/gstinterpolationcontrolsource.h /epoc32/include/platform/mw/gstreamer/gst/controller/gstinterpolationcontrolsource.h
+../libs/gst/controller/gstcontroller.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/controller/gstcontroller.h )
+../libs/gst/controller/gstcontrolsource.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/controller/gstcontrolsource.h )
+../libs/gst/controller/gstinterpolationcontrolsource.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/controller/gstinterpolationcontrolsource.h )
//dataprotocol
-../libs/gst/dataprotocol/dataprotocol.h /epoc32/include/platform/mw/gstreamer/gst/dataprotocol/dataprotocol.h
+../libs/gst/dataprotocol/dataprotocol.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/dataprotocol/dataprotocol.h )
//net
-../libs/gst/net/gstnetclientclock.h /epoc32/include/platform/mw/gstreamer/gst/net/gstnetclientclock.h
-../libs/gst/net/gstnet.h /epoc32/include/platform/mw/gstreamer/gst/net/gstnet.h
-../libs/gst/net/gstnettimepacket.h /epoc32/include/platform/mw/gstreamer/gst/net/gstnettimepacket.h
-../libs/gst/net/gstnettimeprovider.h /epoc32/include/platform/mw/gstreamer/gst/net/gstnettimeprovider.h
+../libs/gst/net/gstnetclientclock.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/net/gstnetclientclock.h )
+../libs/gst/net/gstnet.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/net/gstnet.h )
+../libs/gst/net/gstnettimepacket.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/net/gstnettimepacket.h )
+../libs/gst/net/gstnettimeprovider.h MW_LAYER_PLATFORM_EXPORT_PATH(gstreamer/gst/net/gstnettimeprovider.h )
--- a/internal/gstplayer/data/gstplayer.rss Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,350 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-/*
-* ==============================================================================
-* Name : GSTPlayer.rss
-* Part of : GSTPlayer
-* Interface :
-* Description :
-* Version :
-*
-
-* ==============================================================================
-*/
-
-// RESOURCE IDENTIFIER
-NAME HEWB // 4 letter ID
-
-
-// INCLUDES
-#include <eikon.rh>
-#include <eikon.rsg>
-#include <Avkon.rsg>
-#include <Avkon.hrh>
-#include <Avkon.rh>
-#include <avkon.loc>
-#include <avkon.mbg>
-#include <avkonsct.loc>
-#include <avkon.rsg>
-#include <appinfo.rh>
-
-#include <CommonDialogs.hrh>
-#include <CommonDialogs.rh>
-#include <PathConfiguration.hrh>
-
-#include "GSTPlayer.hrh"
-#include "GSTPlayer.rls"
-
-#define KWidth 176
-#define KHeight 100
-#define KMaxLength 256
-
-// RESOURCE DEFINITIONS
-// -----------------------------------------------------------------------------
-//
-// Define the resource file signature
-// This resource should be empty.
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE RSS_SIGNATURE
- {
- }
-
-// -----------------------------------------------------------------------------
-//
-// Default Document Name
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE TBUF r_default_document_name
- {
- buf="HEWB";
- }
-
-// -----------------------------------------------------------------------------
-//
-// Define default menu and CBA key.
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE EIK_APP_INFO
- {
- menubar = r_gstplayer_menubar;
- cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT;
- }
-
-
-// -----------------------------------------------------------------------------
-//
-// r_helloworldbasic_menubar
-// Menubar for HelloWorldBasic example
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE MENU_BAR r_gstplayer_menubar
- {
- titles =
- {
- MENU_TITLE { menu_pane = r_gstplayer_menu; }
- };
- }
-
-RESOURCE MENU_PANE r_play_cmd
- {
- items=
- {
- MENU_ITEM{command = EGSTPlayerNewSong;txt = "New Song";},
- MENU_ITEM{command = EGSTPlayerPlay;txt = "Play";},
- MENU_ITEM{command = EGSTPlayerSamplesPlayed; txt = "Samples Played"; },
- MENU_ITEM{command = EGSTPlayerSkPadCaps;txt = "Sink Pad Caps";cascade=r_sinkpad_caps;},
- MENU_ITEM{command = EGSTPlayerVolume;txt = "Volume"; cascade=r_volume_cmds;}
- };
- }
-
-RESOURCE MENU_PANE r_record_cmd
- {
- items=
- {
- MENU_ITEM{command = EGSTPlayerRecordWav;txt = "Record WAV";},
- MENU_ITEM{command = EGSTPlayerRecordAac;txt = "Record AAC";},
- MENU_ITEM{command = EGSTPlayerRecordRaw;txt = "Record RAW";},
- MENU_ITEM{command = EGSTPlayerRecordAmr;txt = "Record AMR";},
- MENU_ITEM{command = EGSTPlayerRecordG711;txt = "Record G711";},
- MENU_ITEM{command = EGSTPlayerRecordG729;txt = "Record G729";},
- MENU_ITEM{command = EGSTPlayerRecordIlbc;txt = "Record ILBC";},
- MENU_ITEM { command = EGSTPlayerSamplesRecorded; txt = "Samples Recorded"; },
- MENU_ITEM{command = EGSTPlayerSourcePadCaps;txt = "Source Pad Caps";cascade=r_srcpad_caps;},
- MENU_ITEM{command = EGSTPlayerGain;txt = "Gain"; cascade=r_gain_cmds;}
- };
- }
-
-RESOURCE MENU_PANE r_volume_cmds
- {
- items=
- {
- MENU_ITEM { command = EGSTPlayerCurrentVolume; txt = "Current Volume"; },
- MENU_ITEM { command = EGSTPlayerMaxVolume; txt = "Max Volume"; },
- MENU_ITEM { command = EGSTPlayerVolumeUp; txt = "Volume up"; },
- MENU_ITEM { command = EGSTPlayerVolumeDown; txt = "Volume down"; },
- MENU_ITEM { command = EGSTPlayerRightBalance; txt = "Right Balance"; },
- MENU_ITEM { command = EGSTPlayerLeftBalance; txt = "Left Balance"; }
- };
- }
-
-RESOURCE MENU_PANE r_gain_cmds
- {
- items=
- {
- MENU_ITEM { command = EGSTPlayerCurrentGain; txt = "Current Gain"; },
- MENU_ITEM { command = EGSTPlayerMaxGain; txt = "Max Gain"; },
- MENU_ITEM { command = EGSTPlayerGainUp; txt = "Gain up"; },
- MENU_ITEM { command = EGSTPlayerGainDown; txt = "Gain down"; }
- // MENU_ITEM { command = EGSTPlayerRightBalance; txt = "Right Balance"; },
- // MENU_ITEM { command = EGSTPlayerLeftBalance; txt = "Left Balance"; }
- };
- }
-RESOURCE MENU_PANE r_sinkpad_caps
- {
- items=
- {
- MENU_ITEM { command = EGSTPlayerSinkPadCaps; txt = "DevSound sinkpad caps"; },
- MENU_ITEM { command = EGSTPlayerNegotiatedSinkCaps; txt = "Negotiated Sink Caps"; }
- };
- }
-
-RESOURCE MENU_PANE r_srcpad_caps
- {
- items=
- {
- MENU_ITEM { command = EGSTPlayerSrcPadCaps; txt = "DevSound srcpad caps"; },
- MENU_ITEM { command = EGSTPlayerNegotiatedSrcCaps; txt = "Negotiated Src Caps"; }
- };
- }
-
-RESOURCE MENU_PANE r_sample_info
- {
- items=
- {
- MENU_ITEM { command = EGSTPlayerSamplesPlayed; txt = "Samples Played"; },
- MENU_ITEM { command = EGSTPlayerSamplesRecorded; txt = "Samples Recorded"; }//,
- //MENU_ITEM { command = EGSTPlayerTimePlayed; txt = "Time Played"; }
- };
- }
-
-// -----------------------------------------------------------------------------
-//
-// r_helloworldbasic_menu
-// Menu for "Options"
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE MENU_PANE r_gstplayer_menu
- {
- items =
- {
- // added the new Options menu command here
- MENU_ITEM
- {
- command = EGSTPlayerPlayerTest;
- txt = "Play";
- cascade=r_play_cmd;
- },
- MENU_ITEM
- {
- command = EGSTPlayerRecordTest;
- txt = "Record";
- cascade=r_record_cmd;
- },
- MENU_ITEM
- {
- command = EGSTPlayerStop;
- txt = "Stop";
- },
- MENU_ITEM
- {
- command = EGSTPlayerPause;
- txt = "Pause";
- },
- MENU_ITEM
- {
- command = EGSTRecorderStop;
- txt = "Record Stop";
- },
- MENU_ITEM
- {
- command = EGSTPlayerResume;
- txt = "Resume";
- },
- /* MENU_ITEM
- {
- command = EGSTPlayerVolume;
- txt = "Volume";
- cascade=r_volume_cmds;
- },
- */
- /* MENU_ITEM
- {
- command = EGSTPlayerSamplesInfo;
- txt = "Sample info";
- cascade=r_sample_info;
- },
- */
- /* MENU_ITEM
- {
- command = EGSTPlayerPadCaps;
- txt = "Pad Caps";
- cascade=r_pad_caps;
- },
- */
- MENU_ITEM
- {
- command = EAknSoftkeyExit;
- txt = "Exit";
- }
- };
- }
-
-// -----------------------------------------------------------------------------
-//
-// Resources for messages.
-//
-// -----------------------------------------------------------------------------
-//
-RESOURCE TBUF32 r_hewb_command1_text { buf="Select mp3/wav/raw file."; }
-RESOURCE TBUF32 r_hewb_command2_text { buf="Select mp3/wav/raw New Song!"; }
-RESOURCE TBUF32 r_hewb_caption_string { buf="GSTPlayer"; }
-
-
-// ----------------------------------------------------------------------------
-//
-// r_helloworldbasic_localisable_app_info
-//
-// ----------------------------------------------------------------------------
-//
-RESOURCE LOCALISABLE_APP_INFO r_gstplayer_localisable_app_info
- {
- short_caption = "GSTPlayer";
- caption_and_icon =
- CAPTION_AND_ICON_INFO
- {
- caption = "GSTPlayer";
-
- number_of_icons = 1;
- icon_file = "\\resource\\apps\\gstplayer_aif.mif";
- };
- }
-
-/* RESOURCE DIALOG r_res_id_for_a_dialog
-{
- flags = EAknDialogSelectionList;
- buttons = R_AVKON_SOFTKEYS_OK_CANCEL;
- items =
- {
- DLG_LINE
- {
- type = EAknCtSingleListBox;
- id = ESelectionListControl;
- control = LISTBOX
- {
- flags = EAknListBoxSelectionList;
- };
- }
- };
-}
-
-
-
-RESOURCE MENU_BAR r_res_id_for_a_menubar
-{
- titles =
- {
- MENU_TITLE { menu_pane = R_AVKON_MENUPANE_SETTING_LIST ; }
- };
-}*/
-
-RESOURCE RTXTED r_richtexteditor_rich_text_editor
- {
- width = KWidth;
- height = KHeight;
- textlimit = KMaxLength;
- flags = EEikEdwinReadOnly | EEikEdwinAvkonDisableCursor;
- avkon_flags = EAknEditorFlagEnableScrollBars;
- }
-// ---------------------------------------------------------
-//
-// r_musicshop_memory_selection_dialog
-//
-// ---------------------------------------------------------
-//
-RESOURCE MEMORYSELECTIONDIALOG r_musicshop_memory_selection_dialog
- {
- softkey_1 = text_softkey_select;
- locations =
- {
- LOCATION { root_path = text_phone_memory_root_path; },
- LOCATION { root_path = text_memory_card_root_path; }
- };
- }
-
-// End of File
-
--- a/internal/gstplayer/group/gstplayer.mmp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-/*
-* ==============================================================================
-* Name : gstplayer.mmp
-* Part of : GSTPlayer
-* Interface :
-* Description :
-* Version :
-*
-* ==============================================================================
-*/
-
-#include <platform_paths.hrh>
-
-TARGET GSTPlayer.exe
-TARGETTYPE exe
-UID 0x100039CE 0xA000017F
-LANG SC
-VENDORID VID_DEFAULT
-CAPABILITY All -tcb
-
-SECUREID 0xA000017F
-EPOCSTACKSIZE 0x8000
-EPOCHEAPSIZE 0x1000000 0x1000000
-
-SOURCEPATH ../src
-SOURCE GSTPlayer.cpp
-SOURCE GSTPlayerApplication.cpp
-SOURCE GSTPlayerAppView.cpp
-SOURCE GSTPlayerAppUi.cpp
-SOURCE GSTPlayerDocument.cpp
-SOURCE RichTextEditor.cpp
-SOURCE GlibEventHandler.cpp
-SOURCE SymGstreamer.cpp
-
-SOURCEPATH ../data
-
-START RESOURCE GSTPlayer.rss
-HEADER
-TARGETPATH resource/apps
-END //RESOURCE
-
-START RESOURCE GSTPlayer_reg.rss
-DEPENDS gstplayer.rsg
-#ifdef WINSCW
-TARGETPATH /private/10003a3f/apps
-#else
-TARGETPATH /private/10003a3f/import/apps
-#endif
-END //RESOURCE
-
-USERINCLUDE ../inc
-
-MW_LAYER_SYSTEMINCLUDE
-OS_LAYER_LIBC_SYSTEMINCLUDE
-OS_LAYER_GLIB_SYSTEMINCLUDE
-USERINCLUDE ../../../include/gstreamer
-USERINCLUDE ../../../include/gstreamer/gst
-USERINCLUDE ../../../include/gstreamer/gst/base
-USERINCLUDE ../../../include/gstreamer/gst/controller
-USERINCLUDE ../../../include/gstreamer/gst/dataprotocol
-USERINCLUDE ../../../include/gstreamer/gst/net
-
-LIBRARY euser.lib
-LIBRARY apparc.lib
-LIBRARY cone.lib
-LIBRARY eikcore.lib
-LIBRARY avkon.lib
-LIBRARY commonengine.lib
-LIBRARY efsrv.lib
-LIBRARY estor.lib
-LIBRARY PlatformEnv.lib
-LIBRARY CommonDialogs.lib
-LIBRARY eikctl.lib
-LIBRARY eikcoctl.lib
-LIBRARY etext.lib
-LIBRARY ws32.lib
-LIBRARY libc.lib
-LIBRARY libpthread.lib
-LIBRARY libdl.lib
-LIBRARY libm.lib
-LIBRARY libglib.lib
-LIBRARY libgmodule.lib
-LIBRARY libgobject.lib
-LIBRARY libgthread.lib
-LIBRARY glibbackend.lib
-//LIBRARY libpopt.lib
-LIBRARY libz.lib
-//LIBRARY pavFeedsLibXml2.lib
-LIBRARY libgstreamer.lib
-//LIBRARY libgsterrorconcealment.lib
-//LIBRARY libgstg711decoderinterface.lib
-LIBRARY libgstdevsoundext.lib
-LIBRARY MMFDevSound.lib
-
-// End of File
-
-SMPSAFE
--- a/internal/gstplayer/inc/gstplayer.hrh Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-/*
-* ==============================================================================
-* Name : helloworldbasic.hrh
-* Part of : Helloworldbasic
-* Interface :
-* Description :
-* Version :
-*
-
-* ==============================================================================
-*/
-
-#ifndef __GSTPLAYER_HRH__
-#define __GSTPLAYER_HRH__
-
-// GSTPlayer enumerate command codes
-enum TGSTPlayerIds
- {
- EGSTPlayerNewSong = 0x6001, // start value must not be 0
- EGSTPlayerPlayerTest,
- EGSTPlayerRecordTest,
- EGSTPlayerPlay,
- EGSTPlayerStop,
- EGSTRecorderStop,
- EGSTPlayerPause,
- EGSTPlayerResume,
- EGSTPlayerRecordRaw,
- EGSTPlayerRecordWav,
- EGSTPlayerRecordAmr,
- EGSTPlayerRecordG711,
- EGSTPlayerRecordG729,
- EGSTPlayerRecordIlbc,
- EGSTPlayerVolume,
- EGSTPlayerCurrentVolume,
- EGSTPlayerMaxVolume,
- EGSTPlayerVolumeUp,
- EGSTPlayerVolumeDown,
- EGSTPlayerRightBalance,
- EGSTPlayerLeftBalance,
- EGSTPlayerGain,
- EGSTPlayerCurrentGain,
- EGSTPlayerMaxGain,
- EGSTPlayerGainUp,
- EGSTPlayerGainDown,
- EGSTPlayerSamplesPlayed,
- EGSTPlayerSamplesRecorded,
- EGSTPlayerSamplesInfo,
- EGSTPlayerTimePlayed,
-
- EGSTPlayerSkPadCaps,
- EGSTPlayerSourcePadCaps,
-
- EGSTPlayerSinkPadCaps,
- EGSTPlayerSrcPadCaps,
-
- EGSTPlayerNegotiatedSinkCaps,
- EGSTPlayerNegotiatedSrcCaps,
- EGSTPlayerRecordAac
-
-
- };
-
-#endif // __HELLOWORLDBASIC_HRH__
--- a/internal/gstplayer/inc/gstreamer.h Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-#include <e32def.h>
-#include <e32cmn.h>
-#include <gst/gst.h>
-#include <string.h>
-#include "gstplayerappview.h"
-
-extern GstElement *pipeline, *source, *wavparse,*sink,*conv,*resample,*decoder;
-extern GstBus *bus;
-
-extern CGSTPlayerAppView *iGstView;
-
-
-int GstreamerNew(TFileName filename);
-int GstreamerPlay(TFileName filename);
-int gst_play_mp3();
-int gst_play_wave();
-int gst_play_raw();
-int gst_play_amr();
-int gst_play_g711();
-int gst_play_g729();
-int gst_play_ilbc();
-
-int gst_record_raw();
-int gst_record_wav();
-int gst_record_amr();
-int gst_record_g711();
-int gst_record_aac();
-int gst_record_g729();
-int gst_record_ilbc();
-int gst_current_volume();
-int gst_max_volume();
-int gst_volume_up();
-int gst_volume_down();
-
-void ShownoteL();
-
-int gst_current_gain();
-int gst_max_gain();
-int gst_gain_up();
-int gst_gain_down();
-
-int gst_balance();
-void samplesplayed();
-void samplesrecorded();
-void samplesrecorded();
-void getsinkpadcaps();
-void negotiatedsinkcaps();
-void getsrcpadcaps();
-void negotiatedsrccaps();
-
-
--- a/internal/gstplayer/src/GSTPlayerappui.cpp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,462 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-/*
-* ==============================================================================
-* Name : gstplayerappui.cpp
-* Part of : gstplayer
-* Interface :
-* Description :
-* Version :
-*
-
-* ==============================================================================
-*/
-
-// INCLUDE FILES
-#include <avkon.hrh>
-#include <aknnotewrappers.h>
-#include <stringloader.h>
-#include <GSTPlayer.rsg>
-#include <CAknMemorySelectionDialog.h>
-#include <f32file.h>
-#include <s32file.h>
-#include <PathInfo.h>
-#include <gst/gst.h>
-
-#include "GSTPlayer.pan"
-#include "GSTPlayerAppUi.h"
-#include "GSTPlayerAppView.h"
-#include "GSTPlayer.hrh"
-
-#include "GlibEventHandler.h"
-#include "gstreamer.h"
-
-TFileName fileName;
-
-_LIT( KHelloFileName, "\\private\\A000017F\\Hello.txt" );
-_LIT( KHelloText, "HELLO WORLD!");
-
-// ============================ MEMBER FUNCTIONS ===============================
-
-
-// -----------------------------------------------------------------------------
-// CGSTPlayerAppUi::ConstructL()
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CGSTPlayerAppUi::ConstructL()
- {
- // Initialise app UI with standard value.
- BaseConstructL(CAknAppUi::EAknEnableSkin);
- // Here the Hello.txt file can be created, if it is not copied automatically.
- /*
- RFs fsSession;
- User::LeaveIfError(fsSession.Connect());
-
- RFile file;
-
- // Create a file to write the text to
- if ( file.Replace(fsSession, KHelloFileName, EFileWrite ) != KErrNone )
- {
- return;
- }
- CleanupClosePushL( file );
-
- RFileWriteStream outputFileStream( file );
- CleanupClosePushL( outputFileStream );
- outputFileStream << KHelloText;
-
- CleanupStack::PopAndDestroy(2); // file, outputFileStream
-
- fsSession.Close();
- */
-
- // Create view object
- iAppView = CGSTPlayerAppView::NewL(ClientRect() );
-
- iGstView = iAppView;
-
- }
-// -----------------------------------------------------------------------------
-// CGSTPlayerAppUi::CGSTPlayerAppUi()
-// C++ default constructor can NOT contain any code, that might leave.
-// -----------------------------------------------------------------------------
-//
-CGSTPlayerAppUi::CGSTPlayerAppUi()
- {
- // No implementation required
- }
-
-// -----------------------------------------------------------------------------
-// CGSTPlayerAppUi::~CGSTPlayerAppUi()
-// Destructor.
-// -----------------------------------------------------------------------------
-//
-CGSTPlayerAppUi::~CGSTPlayerAppUi()
- {
-
- if (iAppView)
- {
- delete iAppView;
- iAppView = NULL;
- }
-
- }
-
-// -----------------------------------------------------------------------------
-// CGSTPlayerAppUi::HandleCommandL()
-// Takes care of command handling.
-// -----------------------------------------------------------------------------
-//
-void CGSTPlayerAppUi::HandleCommandL(TInt aCommand)
- {
- switch (aCommand)
- {
- case EEikCmdExit:
- case EAknSoftkeyExit:
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- gst_object_unref(GST_OBJECT (pipeline));
-
- }
- Exit();
- break;
-
- case EGSTPlayerNewSong:
- {
- /*TDes& aPath;
- TBool aMemoryCardStorageAllowed;*/
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- gst_object_unref(GST_OBJECT (pipeline));
-
- }
- CAknMemorySelectionDialog* memoryDialog =
- CAknMemorySelectionDialog::NewL(ECFDDialogTypeSave,
- R_MUSICSHOP_MEMORY_SELECTION_DIALOG, EFalse);
- CleanupStack::PushL(memoryDialog);
-
- CAknMemorySelectionDialog::TMemory
- mem(CAknMemorySelectionDialog::EPhoneMemory);
- TFileName ignore;
- //TFileName path;
- if (! (memoryDialog->ExecuteL(mem, &fileName, &ignore) ))
- {
- // User dnt select the memory location.
- // retVal = EFalse;
- }
- else
- {
- //aPath.Copy( path );
- }
- CleanupStack::PopAndDestroy(); // memoryDialog
-
-
- //if user has pressed cancel button, then just return
- if (!ShowDirListL(fileName))
- {
- return;
- } //end if
- if (GstreamerNew(fileName) == -1)
- {
- // Load a string from the resource file and display it
- HBufC* textResource =
- StringLoader::LoadLC( R_HEWB_COMMAND1_TEXT);
- CAknInformationNote* informationNote;
-
- informationNote = new ( ELeave ) CAknInformationNote;
-
- // Show the information Note with
- // textResource loaded with StringLoader.
- informationNote->ExecuteLD( *textResource);
-
- // Pop HBuf from CleanUpStack and Destroy it.
- CleanupStack::PopAndDestroy(textResource);
-
- }
-
- }
- break;
- case EGSTPlayerPlay:
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- if (GstreamerNew(fileName) == -1)
- {
- // Load a string from the resource file and display it
- HBufC* textResource =
- StringLoader::LoadLC( R_HEWB_COMMAND2_TEXT);
- CAknInformationNote* informationNote;
-
- informationNote = new ( ELeave ) CAknInformationNote;
-
- // Show the information Note with
- // textResource loaded with StringLoader.
- informationNote->ExecuteLD( *textResource);
-
- // Pop HBuf from CleanUpStack and Destroy it.
- CleanupStack::PopAndDestroy(textResource);
-
- }
-
- break;
- case EGSTPlayerStop:
- if (pipeline!=NULL)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- gst_object_unref (GST_OBJECT (pipeline));
- pipeline = NULL;
- }
- break;
- case EGSTRecorderStop:
- if (pipeline!=NULL)
- {
- gst_element_send_event (pipeline, gst_event_new_eos ());
- }
- break;
-
- case EGSTPlayerPause:
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_PAUSED);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- break;
-
- case EGSTPlayerResume:
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PAUSED)
- {
-
- gst_element_set_state(pipeline, GST_STATE_PLAYING);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- break;
-
- case EGSTPlayerRecordWav:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_wav();
- }
- break;
- case EGSTPlayerRecordAac:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_aac();
- }
- break;
-
- case EGSTPlayerRecordRaw:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_raw();
- }
- break;
-
- case EGSTPlayerRecordAmr:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_amr();
- }
- break;
-
- case EGSTPlayerRecordG711:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_g711();
- }
- break;
- case EGSTPlayerRecordG729:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_g729();
- }
- break;
- case EGSTPlayerRecordIlbc:
- {
- if (pipeline!=NULL && pipeline ->current_state
- == GST_STATE_PLAYING)
- {
-
- gst_element_set_state(pipeline, GST_STATE_NULL);
- //gst_object_unref (GST_OBJECT (pipeline));
-
- }
- gst_record_ilbc();
- }
- break;
-
- case EGSTPlayerCurrentVolume:
- gst_current_volume();
- break;
- case EGSTPlayerMaxVolume:
- gst_max_volume();
- break;
- case EGSTPlayerVolumeUp:
- gst_volume_up();
- break;
- case EGSTPlayerVolumeDown:
- gst_volume_down();
- break;
- case EGSTPlayerLeftBalance:
- case EGSTPlayerRightBalance:
- gst_balance();
- break;
- case EGSTPlayerCurrentGain:
- gst_current_gain();
- break;
- case EGSTPlayerMaxGain:
- gst_max_gain();
- break;
- case EGSTPlayerGainUp:
- gst_gain_up();
- break;
- case EGSTPlayerGainDown:
- gst_gain_down();
- break;
- case EGSTPlayerSamplesPlayed:
- samplesplayed();
- break;
- case EGSTPlayerSamplesRecorded:
- samplesrecorded();
- break;
- case EGSTPlayerSinkPadCaps:
- getsinkpadcaps();
- break;
- case EGSTPlayerSrcPadCaps:
- getsrcpadcaps();
- break;
- case EGSTPlayerNegotiatedSinkCaps:
- negotiatedsinkcaps();
- break;
- case EGSTPlayerNegotiatedSrcCaps:
- negotiatedsrccaps();
- break;
- default:
- Panic(EGSTPlayerUi);
- break;
- }
- }
-// -----------------------------------------------------------------------------
-// Called by the framework when the application status pane
-// size is changed. Passes the new client rectangle to the
-// AppView
-// -----------------------------------------------------------------------------
-//
-void CGSTPlayerAppUi::HandleStatusPaneSizeChange()
- {
- iAppView->SetRect(ClientRect() );
-
- }
-
-TBool CGSTPlayerAppUi::ShowDirListL(TFileName &filePath)
- {
-
- _LIT(KDialogTitle, "Select File");
-
- TBool ret = CAknFileSelectionDialog::RunDlgLD(filePath, // on return, contains the selected file's name
- PathInfo::PhoneMemoryRootPath(), // default root path for browsing
- KDialogTitle, // Dialog's title
- 0 // Pointer to class implementing
- // MAknFileSelectionObserver. OkToExitL is called
- // when user has selected an file.
- );
-
- return ret;
-
- }
-
-void ShowNoteL()
- {
- // Load a string from the resource file and display it
- HBufC* textResource = StringLoader::LoadLC( R_HEWB_COMMAND1_TEXT);
- CAknInformationNote* informationNote;
-
- informationNote = new ( ELeave ) CAknInformationNote;
-
- // Show the information Note with
- // textResource loaded with StringLoader.
- informationNote->ExecuteLD( *textResource);
-
- // Pop HBuf from CleanUpStack and Destroy it.
- CleanupStack::PopAndDestroy(textResource);
- }
-// End of File
-
--- a/internal/gstplayer/src/SymGstreamer.cpp Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1268 +0,0 @@
-/*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser 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
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser 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.
-*
-* Description:
-*
-*/
-
-#include "gstreamer.h"
-#include "GlibEventHandler.h"
-#include <avkon.hrh>
-#include <aknnotewrappers.h>
-#include <stringloader.h>
-#include <GSTPlayer.rsg>
-#include <CAknMemorySelectionDialog.h>
-#include <e32base.h>
-#include <stdlib.h>
-#include <mmf/server/sounddevice.h>
-
-#include "gstplayerappview.h"
-
-GstElement *pipeline, *source, *wavparse,*sink,*decoder,*conv,*resample,*record,*fakesink,*filesink,*encoder,*filter,*wavenc, *amrmux, *aacenc, *mp4mux;
-GstBus *bus;
-GstCaps* caps;
-GstState current,pending;
-char carray[1024];
-
-CGSTPlayerAppView *iGstView;
-
-GstPad *dssinkpad;
-GstCaps *dssinkcap;
-GstPad *dssrcpad;
-GstCaps *dssrccap;
-GstStructure *str;
-
-gboolean negcaps = FALSE;
-
-static gboolean print_field (GQuark field, const GValue *value, gpointer pfx);
-static void print_caps (const GstCaps *caps, const gchar *pfx);
-
-
-
-static void
-cb_raw_playback_handoff (GstElement *src, GstBuffer *buffer, GstPad *pad,
- gpointer user_data)
- {
- static gint readbytes = 0;
- static gboolean eofReached = FALSE;
-
- size_t readsize;
- gint size;
- FILE *f;
- GstCaps *bufCaps;
- if ( eofReached == TRUE )
- {
- //gst_element_set_state (pipeline, GST_STATE_NULL);
- // gst_object_unref (GST_OBJECT (pipeline));
- if ( gst_element_send_event (src, gst_event_new_eos ()) == TRUE )
- {
- g_print ("posted eos");
- }
-
- else
- {
- //g_print ("unable to post eos");
- }
- return;
- }
-
- readsize = 0;
- f = fopen (carray, "r");
- eofReached = TRUE;
- if ( fseek(f, readbytes, 0) == 0 )
- {
- readsize = fread (GST_BUFFER_DATA (buffer),1,GST_BUFFER_SIZE (buffer),f);
- eofReached = FALSE;
- GST_BUFFER_SIZE (buffer) = readsize;
- }
- fclose(f);
-
- size = GST_BUFFER_SIZE (buffer);
- readbytes += readsize;
- if ( (readsize < size) || (readsize == 0) )
- {
- eofReached = TRUE;
- }
-
- bufCaps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- gst_buffer_set_caps(buffer,bufCaps);
-
- }
-
-static void
-cb_play_mp3_handoff (GstElement *fakesrc,
- GstBuffer *buffer,
- GstPad *pad,
- gpointer user_data)
-{
-GstCaps *bufCaps;
- static gint readbytes = 0;
- size_t readsize = 0;
- int size = GST_BUFFER_SIZE (buffer);
-
- FILE *f = fopen (carray, "r");
- fseek(f,readbytes,0);
- readsize = fread(GST_BUFFER_DATA (buffer),1,GST_BUFFER_SIZE (buffer),f);
- readbytes += readsize;
- GST_BUFFER_SIZE (buffer) = readsize;
- if(readsize == 0)
- {
- gst_element_send_event(fakesrc,gst_event_new_eos());
- }
- fclose(f);
-
-}
-static void
-cb_record_raw_handoff (GstElement *fakesrc,
- GstBuffer *buffer,
- GstPad *pad,
- gpointer user_data)
-{
- int size = GST_BUFFER_SIZE (buffer);
- //g_print ("[%u]", size);
- FILE *f = fopen (carray, "a");
- fwrite(GST_BUFFER_DATA (buffer),1,GST_BUFFER_SIZE (buffer),f);
- fclose(f);
-}
-
-
-static gboolean
-bus_call (GstBus *bus,
- GstMessage *msg,
- gpointer data)
-{
- switch (GST_MESSAGE_TYPE (msg)) {
- case GST_MESSAGE_EOS:
- gst_element_set_state (pipeline, GST_STATE_NULL);
- gst_object_unref (GST_OBJECT (pipeline));
- break;
- case GST_MESSAGE_ERROR: {
- gchar *debug;
- GError *err;
- gst_message_parse_error (msg, &err, &debug);
- g_free (debug);
- g_print ("Error: %s\n", err->message);
- g_error_free (err);
- break;
- }
- default:
- break;
- }
-
- return TRUE;
-}
-
-
-static void
-new_pad_cb (GstElement *wavparse, GstPad *new_pad, gpointer pipeline)
- {
- //GstElement *sink,*conv,*resample;
- gst_element_set_state ((_GstElement *)pipeline, GST_STATE_PAUSED);
- sink = gst_element_factory_make ("devsoundsink", "sink");
- conv = gst_element_factory_make ("audioconvert", "audioconvert");
- if (!conv) {
- g_print ("could not create \"audioconvert\" element!");
- return;
- }
- resample = gst_element_factory_make ("audioresample", "audioresample");
- if (!resample) {
- g_print ("could not create \"audioresample\" element!");
- return ;
- }
- gst_bin_add_many(GST_BIN (pipeline), conv, resample, sink, NULL);
-
- // if (!gst_element_link (wavparse, sink))
- // g_error ("link(wavparse, sink) failed!\n");
-
- if(! gst_element_link_many (wavparse,conv, resample, sink, NULL))
- g_print ("link(wavparse,conv,remaple sink) failed!\n");
-
- gst_element_set_state ((_GstElement *)pipeline, GST_STATE_PLAYING);
- }
-
- #define FILENAME 1024
- int GstreamerNew(TFileName filename)
- {
- size_t ret;
-
- ret = wcstombs(carray, (const wchar_t *)filename.PtrZ(), FILENAME);
- int file_type=0;
-
-
-
- char *p;
- p = strrchr(carray, '.');
-
- if ((p != NULL) && (strcmp(p, ".mp3") == 0))
- {
- file_type=2;
- }
- else if ((p != NULL) && (strcmp(p, ".wav") == 0))
- {
- file_type=1;
- }
- else if ((p != NULL) && (strcmp(p, ".raw") == 0))
- {
- file_type=3;
- }
- else if ((p != NULL) && (strcmp(p, ".amr") == 0))
- {
- file_type=4;
- }
- else if ((p != NULL) && (strcmp(p, ".g711") == 0))
- {
- file_type=5;
- }
- else if ((p != NULL) && (strcmp(p, ".g729") == 0))
- {
- file_type=6;
- }
- else if ((p != NULL) && (strcmp(p, ".lbc") == 0))
- {
- file_type=7;
- }
- else
- return -1;
-
- if(file_type==1)
- {
- gst_play_wave();
- }
- else if(file_type==2)
- {
- gst_play_mp3();
- }
- else if(file_type==3)
- {
- gst_play_raw();
- }
- else if(file_type==4)
- {
- gst_play_amr();
- }
- else if(file_type==5)
- {
- gst_play_g711();
- }
- else if(file_type==6)
- {
- gst_play_g729();
- }
- else if(file_type==7)
- {
- gst_play_ilbc();
- }
-
- else
- {
- return 0;
- }
- }
-
-
-int gst_play_mp3()
-{
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- //sink = gst_element_factory_make ("fakesink", "sink");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/mp3",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 16000,
- "channels", G_TYPE_INT, 2, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- //gst_element_link (source, sink);
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
-}
-
- int gst_play_wave()
- {
- /* create elements */
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "pavsrc");
- wavparse = gst_element_factory_make ("wavparse", "parse");
-
- /* set filename property on the file source */
- g_object_set (G_OBJECT (source), "location", carray, NULL);
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
- gst_bin_add_many (GST_BIN (pipeline), source, wavparse, NULL);
- if (!gst_element_link (source, wavparse))
- g_error ("link(src, wavparse) failed!\n");
-
-
- g_signal_connect (wavparse, "pad-added", G_CALLBACK (new_pad_cb),pipeline);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- return 0;
- }
-
- int gst_record_wav()
- {
-
- iGstView->DrawText(_L("Recording Wave"),KRgbBlack);
-
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new("pipeline");
-
- record = gst_element_factory_make("devsoundsrc", "record_audio");
- if (!record)
- {
- g_print("could not create \"record\" element!");
- return -1;
- }
- //g_object_set (G_OBJECT (record), "num-buffers", 5000 , NULL);
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- wavenc = gst_element_factory_make("wavenc", "wavencoder");
- if (!wavenc)
- {
- g_print("could not create \"wavenc\" element!");
- return -1;
- }
-
- _LIT(KFILENAME,"c:\\data\\test.wav");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- // char carray[FILENAME];
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
-
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
- bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
- gst_bus_add_watch(bus, bus_call, NULL);
- gst_object_unref(bus);
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,wavenc,filesink, NULL);
-
- /* link the elements */
- //gst_element_link_many(record, wavenc,filesink, NULL);
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 16000,
- "channels", G_TYPE_INT, 1, NULL);
-
- gst_element_link_filtered (record, wavenc, caps);
- gst_element_link (wavenc, filesink);
- gst_caps_unref (caps);
- iGstView->DrawText(_L("pipeline created\n"),KRgbBlack);
- /* start recording */
- gst_element_set_state(pipeline, GST_STATE_PLAYING);
- iGstView->DrawText(_L("set to play wave file\n"),KRgbBlack);
- return 0;
- }
-
-
- int gst_record_aac()
- {
- GstPad *qtsinkpad,*aacencsrcpad;
- iGstView->DrawText(_L("Recording aac"),KRgbBlack);
-
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new("pipeline");
-
- record = gst_element_factory_make("devsoundsrc", "record_audio");
- if (!record)
- {
- g_print("could not create \"record\" element!");
- return -1;
- }
- //g_object_set (G_OBJECT (record), "num-buffers", 5000 , NULL);
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- aacenc = gst_element_factory_make("nokiaaacenc", "nokiaaacenc");
- if (!aacenc)
- {
- g_print("could not create \"aacenc\" element!");
- return -1;
- }
-
- mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
- if (!mp4mux)
- {
- g_print("could not create \"mp4mux\" element!");
- return -1;
- }
- //name = gst_pad_get_name( sinkpad );
-
- _LIT(KFILENAME,"c:\\data\\test.mp4");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- // char carray[FILENAME];
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
-
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
- bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
- gst_bus_add_watch(bus, bus_call, NULL);
- gst_object_unref(bus);
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,aacenc,mp4mux,filesink, NULL);
-
- /* link the elements */
- //gst_element_link_many(record, aacenc,filesink, NULL);
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 16000,
- "channels", G_TYPE_INT, 1, NULL);
-
- gst_element_link_filtered (record, aacenc, caps);
- qtsinkpad = gst_element_get_request_pad( mp4mux, "audio_%d");
- aacencsrcpad = gst_element_get_pad( aacenc, "src");
- if (gst_pad_link (aacencsrcpad,qtsinkpad) != GST_PAD_LINK_OK) {
-
- g_print("gst_pad_link (aacencsrcpad,qtsinkpad) failed");
- return -1;
- }
- //gst_element_link (aacenc, filesink);
- gst_element_link (mp4mux, filesink);
- gst_caps_unref (caps);
- iGstView->DrawText(_L("pipeline created\n"),KRgbBlack);
- /* start recording */
- gst_element_set_state(pipeline, GST_STATE_PLAYING);
- iGstView->DrawText(_L("set to play aac file\n"),KRgbBlack);
- return 0;
- }
-
- int gst_record_amr()
- {
- iGstView->DrawText(_L("Recording AMR-NB"),KRgbRed);
-
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new ("pipeline");
-
- //g_print ("pipeline created");
- record = gst_element_factory_make ("devsoundsrc", "record_audio");
- // encoder = gst_element_factory_make ("wavenc", NULL);
- if (!record) {
- g_print ("could not create \"record\" element!");
- iGstView->DrawText(_L("Devsound src not available"),KRgbRed);
- return -1;
- }
-
-
- amrmux = gst_element_factory_make ("amrmux", "muxer");
- // encoder = gst_element_factory_make ("wavenc", NULL);
- if (!amrmux) {
- g_print ("could not create \"amrmuxer\" element!");
- iGstView->DrawText(_L("amrmuxer not available"),KRgbRed);
- return -1;
- }
-
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- caps = gst_caps_new_simple ("audio/amr",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
-
- g_object_set (G_OBJECT (record),
- "blocksize", 1280,
- NULL);
-
- _LIT(KFILENAME,"c:\\data\\recordtest.amr");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,amrmux,filesink , NULL);
- /* link the elements */
- gst_element_link_filtered (record, amrmux, caps);
-
- gst_element_link( amrmux, filesink );
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
- int gst_record_g711()
- {
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new ("pipeline");
-
- //g_print ("pipeline created");
- record = gst_element_factory_make ("devsoundsrc", "record_audio");
- // encoder = gst_element_factory_make ("wavenc", NULL);
- if (!record) {
- g_print ("could not create \"record\" element!");
- return -1;
- }
-
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- caps = gst_caps_new_simple ("audio/x-alaw",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- g_object_set (G_OBJECT (record),
- "blocksize", 1280,
- NULL);
-
- _LIT(KFILENAME,"c:\\data\\recordtest.g711");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,filesink , NULL);
- /* link the elements */
- gst_element_link_filtered (record, filesink, caps);
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
- int gst_record_g729()
- {
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new ("pipeline");
-
- record = gst_element_factory_make ("devsoundsrc", "record_audio");
- if (!record) {
- g_print ("could not create \"record\" element!");
- return -1;
- }
-
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- caps = gst_caps_new_simple ("audio/g729",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- g_object_set (G_OBJECT (record),
- "blocksize", 1280,
- NULL);
-
- _LIT(KFILENAME,"c:\\data\\recordtest.g729");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,filesink , NULL);
- /* link the elements */
- gst_element_link_filtered (record, filesink, caps);
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
- int gst_record_ilbc()
- {
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new ("pipeline");
-
- record = gst_element_factory_make ("devsoundsrc", "record_audio");
- if (!record) {
- g_print ("could not create \"record\" element!");
- return -1;
- }
-
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
-
- caps = gst_caps_new_simple ("audio/ilbc",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- g_object_set (G_OBJECT (record),
- "blocksize", 1280,
- NULL);
-
- _LIT(KFILENAME,"c:\\data\\recordtest.lbc");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
- g_object_set(G_OBJECT (filesink), "location", carray, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,filesink , NULL);
- /* link the elements */
- gst_element_link_filtered (record, filesink, caps);
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
- int gst_record_raw()
- {
-
- /* create a new bin to hold the elements */
- pipeline = gst_pipeline_new ("pipeline");
-
- //g_print ("pipeline created");
- record = gst_element_factory_make ("devsoundsrc", "record_audio");
- // encoder = gst_element_factory_make ("wavenc", NULL);
- if (!record) {
- g_print ("could not create \"record\" element!");
- return -1;
- }
- //g_print ("record created");
- filesink = gst_element_factory_make("filesink", "filesink");
- if (!filesink)
- {
- g_print("could not create \"filesink\" element!");
- return -1;
- }
- //GstRingBufferSpec
- //g_print ("sink created");
- caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- //g_print ("caps created");
- g_object_set (G_OBJECT (record),
- //"signal-handoffs", TRUE,
- "blocksize", 1280,
- // "gain",10000,
- NULL);
-
- /*g_object_set (G_OBJECT (fakesink),
- "signal-handoffs", TRUE,
- "sizemax", 4096,
- "sizetype", 2, NULL);*/
-
- _LIT(KFILENAME,"c:\\data\\test.raw");
- TFileName fn;
- fn.Append(KFILENAME);
- TInt ret;
- //char carray[FILENAME];
- carray[0]='\0';
- ret = wcstombs(carray, (const wchar_t *)fn.PtrZ(), FILENAME);
-
-
- g_object_set (G_OBJECT (filesink), "location", carray,"buffer-size",1280, NULL);
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch (bus, bus_call, NULL);
- gst_object_unref (bus);
-
-
- /* add objects to the main pipeline */
- gst_bin_add_many(GST_BIN (pipeline),record,filesink , NULL);
- //g_print ("added to pipe");
- /* link the elements */
- //gst_element_link(record,/*encoder,*/ fakesink/*audiosink*/);
- gst_element_link_filtered (record, filesink, caps);
- //g_signal_connect (fakesink, "handoff", G_CALLBACK (cb_record_raw_handoff), NULL);
- /* start recording */
- // g_print ("start pipe");
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
-
- int gst_play_raw()
- {
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- //sink = gst_element_factory_make ("fakesink", "sink");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
-caps = gst_caps_new_simple ("audio/x-raw-int",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- /*g_object_set (G_OBJECT(source),
- "signal-handoffs", TRUE,
- //"num-buffers", 4,
- "sizemax", 4096,
- "sizetype", 2,
- NULL);*/
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
-// g_signal_connect (source, "handoff", G_CALLBACK (cb_raw_playback_handoff), NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- //gst_element_link (source, sink);
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
-while (caps->refcount > 1)
- {
- gst_caps_unref (caps);
- }
- gst_caps_unref (caps);
-
-
- return 0;
- }
-
- int gst_play_amr()
- {
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- //sink = gst_element_factory_make ("fakesink", "sink");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/amr",
- "width", G_TYPE_INT, 8,
- "depth", G_TYPE_INT, 8,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
-
- int gst_play_g711()
- {
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/x-alaw",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
- int gst_play_g729()
- {
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/g729",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- return 0;
- }
- int gst_play_ilbc()
- {
- /* create elements */
- gboolean link_ok;
-
- pipeline = gst_pipeline_new ("pipeline");
- source = gst_element_factory_make ("filesrc", "filesrc");
- sink = gst_element_factory_make ("devsoundsink", "sink");
-
- caps = gst_caps_new_simple ("audio/ilbc",
- "width", G_TYPE_INT, 16,
- "depth", G_TYPE_INT, 16,
- "signed",G_TYPE_BOOLEAN, TRUE,
- "endianness",G_TYPE_INT, G_BYTE_ORDER,
- "rate", G_TYPE_INT, 8000,
- "channels", G_TYPE_INT, 1, NULL);
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
- gst_bus_add_watch( bus, bus_call, NULL);
- gst_object_unref (bus);
-
- g_object_set (G_OBJECT (source), "location", carray, NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
-
- link_ok = gst_element_link_filtered (source, sink, caps);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- return 0;
- }
-
-
- //******
- int gst_current_volume()
- {
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return -1;
- }
- int vol;
- TBuf<25> currentvolume(_L("current volume "));
- g_object_get(G_OBJECT(sink),
- "volume",&vol,NULL);
-
- currentvolume.AppendNum(vol);
-
- iGstView->DrawText(currentvolume,KRgbBlack);
- return 0;
- }
-
- int gst_max_volume()
- {
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return -1;
- }
-
- int maxvol;
- TBuf<25> maxvolume(_L("max volume "));
-
- g_object_get(G_OBJECT(sink),
- "maxvolume",&maxvol,NULL);
-
- maxvolume.AppendNum(maxvol);
-
- iGstView->DrawText(maxvolume,KRgbBlack);
- return 0;
-
- }
- int gst_volume_up()
- {
-
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return -1;
- }
- iGstView->DrawText(_L("volume up"),KRgbBlack);
- int maxvol;
- g_object_get(G_OBJECT(sink),
- "maxvolume",&maxvol,NULL);
- g_object_set (G_OBJECT (sink),
- "volume", maxvol, NULL);
- return 0;
- }
-
- int gst_volume_down()
- {
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return -1;
- }
-
- iGstView->DrawText(_L("volume down"),KRgbBlack);
- int maxvol;
- g_object_get(G_OBJECT(sink),
- "maxvolume",&maxvol,NULL);
- g_object_set (G_OBJECT (sink),
- "volume", maxvol/2, NULL);
- return 0;
- }
-
- int gst_current_gain()
- {
- if(!record)
- {
- iGstView->DrawText(_L("Devsound source not available"),KRgbRed);
- return -1;
- }
- int gain;
- TBuf<25> currentgain(_L("current gain "));
- g_object_get(G_OBJECT(record),
- "gain",&gain,NULL);
-
- currentgain.AppendNum(gain);
-
- iGstView->DrawText(currentgain,KRgbBlack);
- return 0;
- }
-
- int gst_max_gain()
- {
- if(!record)
- {
- iGstView->DrawText(_L("Devsound source not available"),KRgbRed);
- return -1;
- }
-
- int max;
- TBuf<25> maxgain(_L("max gain "));
-
- g_object_get(G_OBJECT(record),
- "maxgain",&max,NULL);
-
- maxgain.AppendNum(max);
-
- iGstView->DrawText(maxgain,KRgbBlack);
- return 0;
-
- }
- int gst_gain_up()
- {
-
- if(!record)
- {
- iGstView->DrawText(_L("Devsound source not available"),KRgbRed);
- return -1;
- }
- int max;
- g_object_get(G_OBJECT(record),
- "maxgain",&max,NULL);
-
- iGstView->DrawText(_L("gain up"),KRgbBlack);
- g_object_set (G_OBJECT (record),
- "gain", max, NULL);
- return 0;
- }
-
- int gst_gain_down()
- {
- if(!record)
- {
- iGstView->DrawText(_L("Devsound source not available"),KRgbRed);
- return -1;
- }
- int max;
- g_object_get(G_OBJECT(record),
- "maxgain",&max,NULL);
- iGstView->DrawText(_L("gain down"),KRgbBlack);
- g_object_set (G_OBJECT (sink),
- "gain", max/2, NULL);
- return 0;
- }
-
-
-
- int gst_balance()
- {
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return -1;
- }
-
- iGstView->DrawText(_L("balance"),KRgbBlack);
- /* g_object_set (G_OBJECT (sink),
- "left balance", 5000,
- "right balance",5000,NULL);
- */
- return 0;
- }
-
- void samplesplayed()
- {
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- }
- int samples;
- TBuf<25> samplesplayed(_L("samples played "));
- g_object_get (G_OBJECT (sink),
- "samples played", &samples, NULL);
-
- samplesplayed.AppendNum(samples);
- iGstView->DrawText(samplesplayed,KRgbBlack);
- }
-
- void samplesrecorded()
- {
- if(!record)
- {
- iGstView->DrawText(_L("Devsound src not available"),KRgbRed);
- }
- int samples;
- TBuf<25> samplesrecorded(_L("samples recorded "));
- g_object_get (G_OBJECT (record),
- "samples recorded", &samples, NULL);
-
- samplesrecorded.AppendNum(samples);
- iGstView->DrawText(samplesrecorded,KRgbBlack);
- }
-
- static gboolean print_field (GQuark field, const GValue *value, gpointer pfx)
- {
- gchar *str = gst_value_serialize (value);
-
- const gchar* c;
-
- RDebug::Printf("%s %15s: %s\n", (gchar *) pfx, c = g_quark_to_string (field), str);
-
- if(negcaps)
- {
- TPtrC8 property((const TText8*)c);
- TPtrC8 val((const TText8*)str);
- TBuf<10> appdval;
- appdval.Copy(val);
-
- TBuf<25> name;
- name.Copy(property);
- name.Append(':');
- name.Append(appdval);
-
- iGstView->DrawText(name,KRgbBlack);
- }
- g_free (str);
- return TRUE;
- }
-
- static void print_caps (const GstCaps *caps, const gchar *pfx)
- {
- guint i;
-
- g_return_if_fail (caps != NULL);
-
- if (gst_caps_is_any (caps)) {
- RDebug::Printf("%sANY\n", pfx);
- return;
- }
- if (gst_caps_is_empty (caps)) {
- RDebug::Printf("%sEMPTY\n", pfx);
- return;
- }
- const gchar *c;
- for (i = 0; i < gst_caps_get_size (caps); i++) {
- GstStructure *structure = gst_caps_get_structure (caps, i);
-
- RDebug::Printf("%s%s\n", pfx,c = gst_structure_get_name (structure));
-
- TPtrC8 fmt((const TText8*)c);
-
- TBuf<25> name;
- name.Copy(fmt);
-
- iGstView->DrawText(name,KRgbBlack);
-
- gst_structure_foreach (structure, print_field, (gpointer) pfx);
- }
- }
-
- void getsinkpadcaps()
- {
- RDebug::Print(_L("Devsound Pad Caps"));
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return;
- }
- negcaps = FALSE;
- dssinkpad = gst_element_get_pad (sink, "sink");
- dssinkcap = gst_pad_get_caps (dssinkpad);
-
- print_caps (dssinkcap, " ");
- }
-
- void negotiatedsinkcaps()
- {
- RDebug::Print(_L("Negotiated caps"));
- if(!sink)
- {
- iGstView->DrawText(_L("Devsound sink not available"),KRgbRed);
- return;
- }
- negcaps = TRUE;
- dssinkpad = gst_element_get_pad (sink, "sink");
- dssinkcap = gst_pad_get_negotiated_caps (dssinkpad);
-
- print_caps (dssinkcap, " ");
- }
-
- void getsrcpadcaps()
- {
- RDebug::Print(_L("Devsound Source Pad Caps"));
- if(!record)
- {
- iGstView->DrawText(_L("Devsound src not available"),KRgbRed);
- return;
- }
- negcaps = FALSE;
- dssrcpad = gst_element_get_pad (record, "src");
- dssrccap = gst_pad_get_caps (dssrcpad);
-
- print_caps (dssrccap, " ");
- }
-
- void negotiatedsrccaps()
- {
- RDebug::Print(_L("Negotiated src caps"));
- if(!record)
- {
- iGstView->DrawText(_L("Devsound src not available"),KRgbRed);
- return;
- }
- negcaps = TRUE;
- dssrcpad = gst_element_get_pad (record, "src");
- dssrccap = gst_pad_get_negotiated_caps (dssrcpad);
-
- print_caps (dssrccap, " ");
-
- }
--- a/internal/miscfiles/copyplugins.bat Fri May 28 18:11:17 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-md \epoc32\release\winscw\udeb\z\sys\bin\plugins
-
-COPY \epoc32\release\winscw\udeb\libgstcoreelements.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstcoreelements.dll
-COPY \epoc32\release\winscw\udeb\libgstcoreindexers.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstcoreindexers.dll
-COPY \epoc32\release\winscw\udeb\libgstwavparse.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstwavparse.dll
-COPY \epoc32\release\winscw\udeb\libgstwavenc.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstwavenc.dll
-COPY \epoc32\release\winscw\udeb\libgstdevsoundsink.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdevsoundsink.dll
-COPY \epoc32\release\winscw\udeb\libgstdevsoundsrc.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdevsoundsrc.dll
-COPY \epoc32\release\winscw\udeb\libgstaudioconvert.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudioconvert.dll
-COPY \epoc32\release\winscw\udeb\libgstaudioresample.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudioresample.dll
-COPY \epoc32\release\winscw\udeb\libgstaudiotestsrc.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudiotestsrc.dll
-COPY \epoc32\release\winscw\udeb\libgstdecodebin.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdecodebin.dll
-COPY \epoc32\release\winscw\udeb\libgstdecodebin2.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstdecodebin2.dll
-COPY \epoc32\release\winscw\udeb\libgstplaybin.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstplaybin.dll
-COPY \epoc32\release\winscw\udeb\libgsttypefindfunctions.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgsttypefindfunctions.dll
-COPY \epoc32\release\winscw\udeb\libgstqueue2.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstqueue2.dll
-COPY \epoc32\release\winscw\udeb\libgstaudiorate.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstaudiorate.dll
-COPY \epoc32\release\winscw\udeb\libgstautodetect.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstautodetect.dll
-COPY \epoc32\release\winscw\udeb\libgstapp.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstapp.dll
-COPY \epoc32\release\winscw\udeb\libgstsubparse.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstsubparse.dll
-COPY \epoc32\release\winscw\udeb\libgstgdp.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstgdp.dll
-COPY \epoc32\release\winscw\udeb\libgstadder.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstadder.dll
-COPY \epoc32\release\winscw\udeb\libgstvolume.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstvolume.dll
-COPY \epoc32\release\winscw\udeb\libgsttcp.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgsttcp.dll
-COPY \epoc32\release\winscw\udeb\gstqtmux.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\gstqtmux.dll
-COPY \epoc32\release\winscw\udeb\libgstnokiaaacenc.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstnokiaaacenc.dll
-COPY \epoc32\release\winscw\udeb\libgstamrmux.dll \epoc32\release\winscw\udeb\z\sys\bin\plugins\libgstamrmux.dll
\ No newline at end of file
--- a/rom/gstreamer.iby Fri May 28 18:11:17 2010 -0500
+++ b/rom/gstreamer.iby Fri Jun 25 17:18:46 2010 -0500
@@ -48,7 +48,6 @@
file=ABI_DIR\BUILD_DIR\libgstriff.dll SHARED_LIB_DIR\libgstriff.dll
file=ABI_DIR\BUILD_DIR\libgsttag.dll SHARED_LIB_DIR\libgsttag.dll
file=ABI_DIR\BUILD_DIR\libgstvideo.dll SHARED_LIB_DIR\libgstvideo.dll
-file=ABI_DIR\BUILD_DIR\libgstphotography.dll SHARED_LIB_DIR\libgstphotography.dll
//file=ABI_DIR\BUILD_DIR\libgstvideorate.dll SHARED_LIB_DIR\libgstvideorate.dll
//file=ABI_DIR\BUILD_DIR\libgstvideoscale.dll SHARED_LIB_DIR\libgstvideoscale.dll
//file=ABI_DIR\BUILD_DIR\libgstvideotestsrc.dll SHARED_LIB_DIR\libgstvideotestsrc.dll
Binary file sis/gstreamer_framework.pkg has changed