int
main (int argc, char **argv)
{
  GstPlay *play;
  GPtrArray *playlist;
  gboolean print_version = FALSE;
  gboolean interactive = TRUE;
  gboolean gapless = FALSE;
  gboolean shuffle = FALSE;
  gdouble volume = -1;
  gchar **filenames = NULL;
  gchar *audio_sink = NULL;
  gchar *video_sink = NULL;
  gchar **uris;
  guint num, i;
  GError *err = NULL;
  GOptionContext *ctx;
  gchar *playlist_file = NULL;
  GOptionEntry options[] = {
    {"version", 0, 0, G_OPTION_ARG_NONE, &print_version,
        N_("Print version information and exit"), NULL},
    {"videosink", 0, 0, G_OPTION_ARG_STRING, &video_sink,
        N_("Video sink to use (default is autovideosink)"), NULL},
    {"audiosink", 0, 0, G_OPTION_ARG_STRING, &audio_sink,
        N_("Audio sink to use (default is autoaudiosink)"), NULL},
    {"gapless", 0, 0, G_OPTION_ARG_NONE, &gapless,
        N_("Enable gapless playback"), NULL},
    {"shuffle", 0, 0, G_OPTION_ARG_NONE, &shuffle,
        N_("Shuffle playlist"), NULL},
    {"no-interactive", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,
          &interactive,
        N_("Disable interactive control via the keyboard"), NULL},
    {"volume", 0, 0, G_OPTION_ARG_DOUBLE, &volume,
        N_("Volume"), NULL},
    {"playlist", 0, 0, G_OPTION_ARG_FILENAME, &playlist_file,
        N_("Playlist file containing input media files"), NULL},
    {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
        N_("Do not print any output (apart from errors)"), NULL},
    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
    {NULL}
  };

  setlocale (LC_ALL, "");

#ifdef ENABLE_NLS
  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);
#endif

  g_set_prgname ("gst-play-" GST_API_VERSION);

  ctx = g_option_context_new ("FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ...");
  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
    return 1;
  }
  g_option_context_free (ctx);

  GST_DEBUG_CATEGORY_INIT (play_debug, "play", 0, "gst-play");

  if (print_version) {
    gchar *version_str;

    version_str = gst_version_string ();
    g_print ("%s version %s\n", g_get_prgname (), PACKAGE_VERSION);
    g_print ("%s\n", version_str);
    g_print ("%s\n", GST_PACKAGE_ORIGIN);
    g_free (version_str);

    g_free (audio_sink);
    g_free (video_sink);
    g_free (playlist_file);

    return 0;
  }

  playlist = g_ptr_array_new ();

  if (playlist_file != NULL) {
    gchar *playlist_contents = NULL;
    gchar **lines = NULL;

    if (g_file_get_contents (playlist_file, &playlist_contents, NULL, &err)) {
      lines = g_strsplit (playlist_contents, "\n", 0);
      num = g_strv_length (lines);

      for (i = 0; i < num; i++) {
        if (lines[i][0] != '\0') {
          GST_LOG ("Playlist[%d]: %s", i + 1, lines[i]);
          add_to_playlist (playlist, lines[i]);
        }
      }
      g_strfreev (lines);
      g_free (playlist_contents);
    } else {
      g_printerr ("Could not read playlist: %s\n", err->message);
      g_clear_error (&err);
    }
    g_free (playlist_file);
    playlist_file = NULL;
  }

  if (playlist->len == 0 && (filenames == NULL || *filenames == NULL)) {
    g_printerr (_("Usage: %s FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ..."),
        "gst-play-" GST_API_VERSION);
    g_printerr ("\n\n"),
        g_printerr ("%s\n\n",
        _("You must provide at least one filename or URI to play."));
    /* No input provided. Free array */
    g_ptr_array_free (playlist, TRUE);

    g_free (audio_sink);
    g_free (video_sink);

    return 1;
  }

  /* fill playlist */
  if (filenames != NULL && *filenames != NULL) {
    num = g_strv_length (filenames);
    for (i = 0; i < num; ++i) {
      GST_LOG ("command line argument: %s", filenames[i]);
      add_to_playlist (playlist, filenames[i]);
    }
    g_strfreev (filenames);
  }

  num = playlist->len;
  g_ptr_array_add (playlist, NULL);

  uris = (gchar **) g_ptr_array_free (playlist, FALSE);

  if (shuffle)
    shuffle_uris (uris, num);

  /* prepare */
  play = play_new (uris, audio_sink, video_sink, gapless, volume);

  if (play == NULL) {
    g_printerr
        ("Failed to create 'playbin' element. Check your GStreamer installation.\n");
    return EXIT_FAILURE;
  }

  if (interactive) {
    if (gst_play_kb_set_key_handler (keyboard_cb, play)) {
      g_print (_("Press 'k' to see a list of keyboard shortcuts.\n"));
      atexit (restore_terminal);
    } else {
      g_print ("Interactive keyboard handling in terminal not available.\n");
    }
  }

  /* play */
  do_play (play);

  /* clean up */
  play_free (play);

  g_free (audio_sink);
  g_free (video_sink);

  g_print ("\n");
  return 0;
}
Beispiel #2
0
void
dump_image_description (ImageDescription * desc)
{
  GST_LOG ("Description %p , size:%" G_GSIZE_FORMAT, desc, desc->idSize);

#if DEBUG_DUMP
  gst_util_dump_mem ((const guchar *) desc, desc->idSize);
#endif

  GST_LOG ("cType : %" GST_FOURCC_FORMAT, QT_FOURCC_ARGS (desc->cType));
  GST_LOG ("version:%d", desc->version);
  GST_LOG ("revisionLevel:%d", desc->revisionLevel);
  GST_LOG ("vendor:%" GST_FOURCC_FORMAT, QT_FOURCC_ARGS (desc->vendor));
  GST_LOG ("temporalQuality:%lu", desc->temporalQuality);
  GST_LOG ("spatialQuality:%lu", desc->spatialQuality);
  GST_LOG ("width:%u", desc->width);
  GST_LOG ("height:%u", desc->height);
  GST_LOG ("hres:%f", desc->hRes / 65536.0);
  GST_LOG ("vres:%f", desc->vRes / 65536.0);
  GST_LOG ("dataSize:%" G_GSIZE_FORMAT, desc->dataSize);
  GST_LOG ("frameCount:%d", desc->frameCount);
  GST_LOG ("name:%.*s", desc->name[0], desc->name + 1);
  GST_LOG ("depth:%d", desc->depth);
  GST_LOG ("clutID:%d", desc->clutID);

  if (desc->idSize > sizeof (ImageDescription)) {
    guint8 *extradata = (guint8 *) desc + sizeof (ImageDescription);
    guint32 type = QT_READ_UINT32 (extradata + 4);

    GST_LOG ("Extra Data size:%lu",
        (gulong) desc->idSize - (gulong) sizeof (ImageDescription));
#if DEBUG_DUMP
    gst_util_dump_mem ((gpointer) (gulong) desc +
        (gulong) sizeof (ImageDescription),
        (gulong) desc->idSize - (gulong) sizeof (ImageDescription));
#endif
    GST_LOG ("Extra Data Type : %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (type));
    if (type == QT_MAKE_FOURCC ('a', 'v', 'c', 'C'))
      dump_avcc_atom (extradata);
  }
}
Beispiel #3
0
/*
 * Read a new buffer from src->reqoffset, takes care of events
 * and seeking and such.
 */
static GstFlowReturn
gst_rtmp_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer)
{
  GstRTMPSrc *src;
  GstBuffer *buf;
  GstMapInfo map;
  guint8 *data;
  guint todo;
  gsize bsize;
  int read;
  int size;

  src = GST_RTMP_SRC (pushsrc);

  g_return_val_if_fail (src->rtmp != NULL, GST_FLOW_ERROR);

  size = GST_BASE_SRC_CAST (pushsrc)->blocksize;

  GST_DEBUG ("reading from %" G_GUINT64_FORMAT
      ", size %u", src->cur_offset, size);

  buf = gst_buffer_new_allocate (NULL, size, NULL);
  if (G_UNLIKELY (buf == NULL)) {
    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
    return GST_FLOW_ERROR;
  }

  bsize = todo = size;
  gst_buffer_map (buf, &map, GST_MAP_WRITE);
  data = map.data;
  read = bsize = 0;

  while (todo > 0) {
    read = RTMP_Read (src->rtmp, (char *) data, todo);

    if (G_UNLIKELY (read == 0 && todo == size)) {
      goto eos;
    } else if (G_UNLIKELY (read == 0)) {
      todo = 0;
      break;
    }

    if (G_UNLIKELY (read < 0))
      goto read_failed;

    if (read < todo) {
      data += read;
      todo -= read;
      bsize += read;
    } else {
      bsize += todo;
      todo = 0;
    }
    GST_LOG ("  got size %d", read);
  }
  gst_buffer_unmap (buf, &map);
  gst_buffer_resize (buf, 0, bsize);

  if (src->discont) {
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
    src->discont = FALSE;
  }

  GST_BUFFER_TIMESTAMP (buf) = src->last_timestamp;
  GST_BUFFER_OFFSET (buf) = src->cur_offset;

  src->cur_offset += size;
  if (src->last_timestamp == GST_CLOCK_TIME_NONE)
    src->last_timestamp = src->rtmp->m_mediaStamp * GST_MSECOND;
  else
    src->last_timestamp =
        MAX (src->last_timestamp, src->rtmp->m_mediaStamp * GST_MSECOND);

  GST_LOG_OBJECT (src, "Created buffer of size %u at %" G_GINT64_FORMAT
      " with timestamp %" GST_TIME_FORMAT, size, GST_BUFFER_OFFSET (buf),
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));


  /* we're done, return the buffer */
  *buffer = buf;

  return GST_FLOW_OK;

read_failed:
  {
    gst_buffer_unref (buf);
    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), ("Failed to read data"));
    return GST_FLOW_ERROR;
  }
eos:
  {
    gst_buffer_unref (buf);
    GST_DEBUG_OBJECT (src, "Reading data gave EOS");
    return GST_FLOW_EOS;
  }
}
Beispiel #4
0
static void
_handoff_handler (GstElement *element, GstBuffer *buffer, GstPad *pad,
  gpointer user_data)
{
  struct SimpleTestStream *st = user_data;
  int i;
  gboolean stop = TRUE;
  GList *codecs = NULL;

  if (st->dat->session == NULL)
    return;

  g_object_get (st->dat->session,
      "codecs", &codecs,
      NULL);

  ts_fail_if (codecs == NULL, "Could not get codecs");

  if (st->flags & WAITING_ON_LAST_CODEC)
  {
    if (fs_codec_are_equal (
        g_list_last (codecs)->data,
        g_object_get_data (G_OBJECT (element), "codec")))
    {
      st->flags &= ~WAITING_ON_LAST_CODEC;
      st->flags |= SHOULD_BE_LAST_CODEC;
      max_buffer_count += st->buffer_count;
      GST_DEBUG ("We HAVE last codec");
    }
    else
    {
#if 0
      gchar *str = fs_codec_to_string (
          g_object_get_data (G_OBJECT (element), "codec"));
      gchar *str2 = fs_codec_to_string (g_list_last (codecs)->data);
      GST_DEBUG ("not yet the last codec, skipping (we have %s, we want %s)",
          str, str2);
      g_free (str);
      g_free (str2);
#endif
      fs_codec_list_destroy (codecs);
      return;
    }
  }


  if (select_last_codec || st->flags & SHOULD_BE_LAST_CODEC)
  {
    if (!fs_codec_are_equal (
            g_list_last (codecs)->data,
            g_object_get_data (G_OBJECT (element), "codec")))
    {
      if (!reset_to_last_codec)
        ts_fail ("The handoff handler got a buffer from the wrong codec"
            " (ie. not the last)");
      fs_codec_list_destroy (codecs);
      return;
    }
  }
  else
    ts_fail_unless (
        fs_codec_are_equal (
            g_list_first (codecs)->data,
            g_object_get_data (G_OBJECT (element), "codec")),
        "The handoff handler got a buffer from the wrong codec");

  fs_codec_list_destroy (codecs);


  st->buffer_count++;
  GST_LOG ("%d:%d: Buffer %d", st->dat->id, st->target->id, st->buffer_count);


  /*
  ts_fail_if (dat->buffer_count > max_buffer_count,
    "Too many buffers %d > max_buffer_count", dat->buffer_count);
  */

  for (i = 0; i < count && !stop ; i++)
  {
    GList *item;


    for (item = g_list_first (dats[i]->streams);
         item;
         item = g_list_next (item))
    {
      struct SimpleTestStream *st2 = item->data;

      if (st2->buffer_count < max_buffer_count)
      {
        stop = FALSE;
        break;
      }
    }
  }

  if (stop)
  {
    if (reset_to_last_codec && !(st->flags & HAS_BEEN_RESET)) {
      GError *error = NULL;
      GList *nego_codecs = NULL;
      gchar *str = NULL;

      g_object_get (st->target->session,
          "codecs", &nego_codecs,
          NULL);

      ts_fail_if (nego_codecs == NULL, "No codecs");
      ts_fail_if (g_list_length (nego_codecs) < 2, "Only one negotiated codec");

      str = fs_codec_to_string (g_list_last (nego_codecs)->data);
      GST_DEBUG ("Setting codec to: %s", str);
      g_free (str);

      ts_fail_unless (fs_session_set_send_codec (st->target->session,
              g_list_last (nego_codecs)->data, &error),
          "Could not set the send codec: %s",
          error ? error->message : "NO GError!!!");
      g_clear_error (&error);

      fs_codec_list_destroy (nego_codecs);

      st->flags |= HAS_BEEN_RESET | WAITING_ON_LAST_CODEC;

      GST_DEBUG ("RESET TO LAST CODEC");

    } else {
      g_main_loop_quit (loop);
    }
  }
}
Beispiel #5
0
static int
run_test (const char *format, ...)
{
  GstStateChangeReturn ret;

  GstElement *pipe, *src, *sink;

  GstBuffer *buf = NULL;

  GstMessage *msg;

  gchar *url;

  va_list args;

  int rc = -1;

  pipe = gst_pipeline_new (NULL);

  src = gst_element_factory_make ("souphttpsrc", NULL);
  fail_unless (src != NULL);

  sink = gst_element_factory_make ("fakesink", NULL);
  fail_unless (sink != NULL);

  gst_bin_add (GST_BIN (pipe), src);
  gst_bin_add (GST_BIN (pipe), sink);
  fail_unless (gst_element_link (src, sink));

  if (http_port == 0) {
    GST_DEBUG ("failed to start soup http server");
  }
  fail_unless (http_port != 0);
  va_start (args, format);
  g_vasprintf (&url, format, args);
  va_end (args);
  fail_unless (url != NULL);
  g_object_set (src, "location", url, NULL);
  g_free (url);

  g_object_set (src, "automatic-redirect", redirect, NULL);
  if (cookies != NULL)
    g_object_set (src, "cookies", cookies, NULL);
  g_object_set (sink, "signal-handoffs", TRUE, NULL);
  g_signal_connect (sink, "preroll-handoff", G_CALLBACK (handoff_cb), &buf);

  if (user_id != NULL)
    g_object_set (src, "user-id", user_id, NULL);
  if (user_pw != NULL)
    g_object_set (src, "user-pw", user_pw, NULL);

  ret = gst_element_set_state (pipe, GST_STATE_PAUSED);
  if (ret != GST_STATE_CHANGE_ASYNC) {
    GST_DEBUG ("failed to start up soup http src, ret = %d", ret);
    goto done;
  }

  gst_element_set_state (pipe, GST_STATE_PLAYING);
  msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
      GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
    gchar *debug = NULL;

    GError *err = NULL;

    gst_message_parse_error (msg, &err, &debug);
    GST_INFO ("error: %s", err->message);
    if (g_str_has_suffix (err->message, "Not Found"))
      rc = 404;
    else if (g_str_has_suffix (err->message, "Forbidden"))
      rc = 403;
    else if (g_str_has_suffix (err->message, "Unauthorized"))
      rc = 401;
    else if (g_str_has_suffix (err->message, "Found"))
      rc = 302;
    GST_INFO ("debug: %s", debug);
    g_error_free (err);
    g_free (debug);
    gst_message_unref (msg);
    goto done;
  }
  gst_message_unref (msg);

  /* don't wait for more than 10 seconds */
  ret = gst_element_get_state (pipe, NULL, NULL, 10 * GST_SECOND);
  GST_LOG ("ret = %u", ret);

  if (buf == NULL) {
    /* we want to test the buffer offset, nothing else; if there's a failure
     * it might be for lots of reasons (no network connection, whatever), we're
     * not interested in those */
    GST_DEBUG ("didn't manage to get data within 10 seconds, skipping test");
    goto done;
  }

  GST_DEBUG ("buffer offset = %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buf));

  /* first buffer should have a 0 offset */
  fail_unless (GST_BUFFER_OFFSET (buf) == 0);
  gst_buffer_unref (buf);
  rc = 0;

done:

  gst_element_set_state (pipe, GST_STATE_NULL);
  gst_object_unref (pipe);
  return rc;
}
Beispiel #6
0
static gboolean
mpegts_base_apply_pat (MpegTSBase * base, GstMpegtsSection * section)
{
  GPtrArray *pat = gst_mpegts_section_get_pat (section);
  GPtrArray *old_pat;
  MpegTSBaseProgram *program;
  gint i;

  if (G_UNLIKELY (pat == NULL))
    return FALSE;

  GST_INFO_OBJECT (base, "PAT");

  /* Applying a new PAT does two things:
   * * It adds the new programs to the list of programs this element handles
   *   and increments at the same time the number of times a program is referenced.
   *
   * * If there was a previously active PAT, It decrements the reference count
   *   of all program it used. If a program is no longer needed, it is removed.
   */

  old_pat = base->pat;
  base->pat = pat;

  GST_LOG ("Activating new Program Association Table");
  /* activate the new table */
  for (i = 0; i < pat->len; ++i) {
    GstMpegtsPatProgram *patp = g_ptr_array_index (pat, i);

    program = mpegts_base_get_program (base, patp->program_number);
    if (program) {
      /* IF the program already existed, just check if the PMT PID changed */
      if (program->pmt_pid != patp->network_or_program_map_PID) {
        if (program->pmt_pid != G_MAXUINT16) {
          /* pmt pid changed */
          /* FIXME: when this happens it may still be pmt pid of another
           * program, so setting to False may make it go through expensive
           * path in is_psi unnecessarily */
          MPEGTS_BIT_UNSET (base->known_psi, program->pmt_pid);
        }

        program->pmt_pid = patp->network_or_program_map_PID;
        if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi, program->pmt_pid)))
          GST_FIXME
              ("Refcounting issue. Setting twice a PMT PID (0x%04x) as know PSI",
              program->pmt_pid);
        MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
      }
    } else {
      /* Create a new program */
      program =
          mpegts_base_add_program (base, patp->program_number,
          patp->network_or_program_map_PID);
    }
    /* We mark this program as being referenced by one PAT */
    program->patcount += 1;
  }

  if (old_pat) {
    MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
    /* deactivate the old table */
    GST_LOG ("Deactivating old Program Association Table");

    for (i = 0; i < old_pat->len; ++i) {
      GstMpegtsPatProgram *patp = g_ptr_array_index (old_pat, i);

      program = mpegts_base_get_program (base, patp->program_number);
      if (G_UNLIKELY (program == NULL)) {
        GST_DEBUG_OBJECT (base, "broken PAT, duplicated entry for program %d",
            patp->program_number);
        continue;
      }

      if (--program->patcount > 0)
        /* the program has been referenced by the new pat, keep it */
        continue;

      GST_INFO_OBJECT (base, "PAT removing program 0x%04x 0x%04x",
          patp->program_number, patp->network_or_program_map_PID);

      if (klass->can_remove_program (base, program)) {
        mpegts_base_deactivate_program (base, program);
        mpegts_base_remove_program (base, patp->program_number);
      }
      /* FIXME: when this happens it may still be pmt pid of another
       * program, so setting to False may make it go through expensive
       * path in is_psi unnecessarily */
      if (G_UNLIKELY (MPEGTS_BIT_IS_SET (base->known_psi,
                  patp->network_or_program_map_PID))) {
        GST_FIXME
            ("Program refcounting : Setting twice a pid (0x%04x) as known PSI",
            patp->network_or_program_map_PID);
      }
      MPEGTS_BIT_SET (base->known_psi, patp->network_or_program_map_PID);
      mpegts_packetizer_remove_stream (base->packetizer,
          patp->network_or_program_map_PID);
    }

    g_ptr_array_unref (old_pat);
  }

  return TRUE;
}
Beispiel #7
0
static void
test_with_caps (GstElement * src, GstElement * videocrop, GstCaps * caps)
{
    GstClockTime time_run;
    GstElement *pipeline;
    GTimer *timer;
    GstBus *bus;
    GstPad *pad;
    guint hcrop;
    guint vcrop;

    /* caps must be writable, we can't check that here though */
    g_assert (GST_CAPS_REFCOUNT_VALUE (caps) == 1);

    timer = g_timer_new ();
    vcrop = 0;
    hcrop = 0;

    pipeline = GST_ELEMENT (gst_element_get_parent (videocrop));
    g_assert (GST_IS_PIPELINE (pipeline));

    /* at this point the pipeline is in PLAYING state; we only want to capture
     * errors resulting from our on-the-fly changing of the filtercaps */
    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));

    /* pad to block */
    pad = gst_element_get_static_pad (src, "src");

    time_run = 0;
    do {
        GstClockTime wait_time, waited_for_block;

        if (check_bus_for_errors (bus, 0))
            break;

        wait_time = GST_SECOND / FRAMERATE;

        GST_LOG ("hcrop = %3d, vcrop = %3d", vcrop, hcrop);

        g_timer_reset (timer);

        /* need to block the streaming thread while changing these properties,
         * otherwise we might get random not-negotiated errors (when caps are
         * changed in between upstream calling pad_alloc_buffer() and pushing
         * the processed buffer?) */
        gst_pad_set_blocked (pad, TRUE);
        g_object_set (videocrop, "left", hcrop, "top", vcrop, NULL);
        gst_pad_set_blocked (pad, FALSE);

        waited_for_block = g_timer_elapsed (timer, NULL) * (double) GST_SECOND;
        /* GST_LOG ("waited: %" GST_TIME_FORMAT ", frame len: %" GST_TIME_FORMAT,
           GST_TIME_ARGS (waited_for_block), GST_TIME_ARGS (wait_time)); */
        ++vcrop;
        ++hcrop;

        if (wait_time > waited_for_block) {
            g_usleep ((wait_time - waited_for_block) / GST_MSECOND);
        }

        time_run += wait_time;
    }
    while (time_run < (TIME_PER_TEST * GST_SECOND));

    g_timer_destroy (timer);
    gst_object_unref (bus);
    gst_object_unref (pad);
}
Beispiel #8
0
static void
gst_ladspa_base_init (gpointer g_class)
{
  GstLADSPAClass *klass = (GstLADSPAClass *) g_class;
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
  GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class);
  LADSPA_Descriptor *desc;
  guint j, audio_in_count, audio_out_count, control_in_count, control_out_count;
  const gchar *klass_tags;
  gchar *longname, *author;
#ifdef HAVE_LRDF
  gchar *uri;
#endif
  gchar *extra_klass_tags = NULL;

  GST_DEBUG ("base_init %p", g_class);

  desc = (LADSPA_Descriptor *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
      descriptor_quark);
  g_assert (desc);
  klass->descriptor = desc;

  /* pad templates */
  gsp_class->num_audio_in = 0;
  gsp_class->num_audio_out = 0;
  /* properties */
  gsp_class->num_control_in = 0;
  gsp_class->num_control_out = 0;

  for (j = 0; j < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      gchar *name = g_strdup ((gchar *) desc->PortNames[j]);

      /* FIXME: group stereo pairs into a stereo pad
       * ladspa-fx have "XXX (Left)" and "XXX (Right)"
       * where XXX={In,Input,Out,Output}
       */

      GST_DEBUG ("LADSPA port name: \"%s\"", name);
      /* replaces all spaces with underscores, and then remaining special chars
       * with '-'
       * FIXME: why, pads can have any name
       */
      g_strdelimit (name, " ", '_');
      g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_-><=", '-');
      GST_DEBUG ("GStreamer pad name: \"%s\"", name);

      if (LADSPA_IS_PORT_INPUT (p))
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SINK, gsp_class->num_audio_in++, 1);
      else
        gst_signal_processor_class_add_pad_template (gsp_class, name,
            GST_PAD_SRC, gsp_class->num_audio_out++, 1);

      g_free (name);
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        gsp_class->num_control_in++;
      else
        gsp_class->num_control_out++;
    }
  }

  longname = g_locale_to_utf8 (desc->Name, -1, NULL, NULL, NULL);
  if (!longname)
    longname = g_strdup ("no description available");
  author = g_locale_to_utf8 (desc->Maker, -1, NULL, NULL, NULL);
  if (!author)
    author = g_strdup ("no author available");

#ifdef HAVE_LRDF
  /* libldrf support, we want to get extra class information here */
  uri = g_strdup_printf (LADSPA_BASE "%ld", desc->UniqueID);
  if (uri) {
    lrdf_statement query = { 0, };
    lrdf_uris *uris;
    gchar *str, *base_type = NULL;

    GST_DEBUG ("uri (id=%d) : %s", desc->UniqueID, uri);
    /* we can take this directly from 'desc', keep this example for future
       attributes. 
       if ((str = lrdf_get_setting_metadata (uri, "title"))) {
       GST_DEBUG ("title : %s", str);
       }
       if ((str = lrdf_get_setting_metadata (uri, "creator"))) {
       GST_DEBUG ("creator : %s", str);
       }
     */

    /* get the rdf:type for this plugin */
    query.subject = uri;
    query.predicate = (char *) RDF_BASE "type";
    query.object = (char *) "?";
    query.next = NULL;
    uris = lrdf_match_multi (&query);
    if (uris) {
      if (uris->count == 1) {
        base_type = g_strdup (uris->items[0]);
        GST_DEBUG ("base_type :  %s", base_type);
      }
      lrdf_free_uris (uris);
    }

    /* query taxonomy */
    if (base_type) {
      uris = lrdf_get_all_superclasses (base_type);
      if (uris) {
        guint32 j;

        for (j = 0; j < uris->count; j++) {
          GST_LOG ("parent_type_uri : %s", uris->items[j]);
          if ((str = lrdf_get_label (uris->items[j]))) {
            GST_DEBUG ("parent_type_label : %s", str);
            if (extra_klass_tags) {
              gchar *old_tags = extra_klass_tags;
              extra_klass_tags = g_strconcat (extra_klass_tags, "/", str, NULL);
              g_free (old_tags);
            } else {
              extra_klass_tags = g_strconcat ("/", str, NULL);
            }
          }
        }
        lrdf_free_uris (uris);
      }
      g_free (base_type);
    }

    /* we can use this for the presets
       uris = lrdf_get_setting_uris (desc->UniqueID);
       if (uris) {
       guint32 j;

       for (j = 0; j < uris->count; j++) {
       GST_INFO ("setting_uri : %s", uris->items[j]);
       if ((str = lrdf_get_label (uris->items[j]))) {
       GST_INFO ("setting_label : %s", str);
       }
       }
       lrdf_free_uris (uris);
       }
     */

  }
  g_free (uri);
#endif

  if (gsp_class->num_audio_in == 0)
    klass_tags = "Source/Audio/LADSPA";
  else if (gsp_class->num_audio_out == 0) {
    if (gsp_class->num_control_out == 0)
      klass_tags = "Sink/Audio/LADSPA";
    else
      klass_tags = "Sink/Analyzer/Audio/LADSPA";
  } else
    klass_tags = "Filter/Effect/Audio/LADSPA";

#ifdef HAVE_LRDF
  if (extra_klass_tags) {
    char *s = g_strconcat (klass_tags, extra_klass_tags, NULL);
    g_free (extra_klass_tags);
    extra_klass_tags = s;
  }
#endif
  GST_INFO ("tags : %s", klass_tags);
  gst_element_class_set_metadata (element_class, longname,
      extra_klass_tags ? extra_klass_tags : klass_tags, longname, author);
  g_free (longname);
  g_free (author);
  g_free (extra_klass_tags);

  klass->audio_in_portnums = g_new0 (gint, gsp_class->num_audio_in);
  klass->audio_out_portnums = g_new0 (gint, gsp_class->num_audio_out);
  klass->control_in_portnums = g_new0 (gint, gsp_class->num_control_in);
  klass->control_out_portnums = g_new0 (gint, gsp_class->num_control_out);

  audio_in_count = audio_out_count = control_in_count = control_out_count = 0;

  for (j = 0; j < desc->PortCount; j++) {
    LADSPA_PortDescriptor p = desc->PortDescriptors[j];

    if (LADSPA_IS_PORT_AUDIO (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        klass->audio_in_portnums[audio_in_count++] = j;
      else
        klass->audio_out_portnums[audio_out_count++] = j;
    } else if (LADSPA_IS_PORT_CONTROL (p)) {
      if (LADSPA_IS_PORT_INPUT (p))
        klass->control_in_portnums[control_in_count++] = j;
      else
        klass->control_out_portnums[control_out_count++] = j;
    }
  }

  g_assert (audio_in_count == gsp_class->num_audio_in);
  g_assert (audio_out_count == gsp_class->num_audio_out);
  g_assert (control_in_count == gsp_class->num_control_in);
  g_assert (control_out_count == gsp_class->num_control_out);

  if (!LADSPA_IS_INPLACE_BROKEN (desc->Properties))
    GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);

  klass->descriptor = desc;
}
Beispiel #9
0
gint
main (gint argc, gchar * argv[])
{

  gst_init (&argc, &argv);

  GST_DEBUG_CATEGORY_INIT (cat_default, "GST_Check_default", 0,
      "default category for this test");
  GST_DEBUG_CATEGORY_INIT (cat2, "GST_Check_2", 0,
      "second category for this test");
#ifndef GST_DISABLE_GST_DEBUG
  g_assert (gst_debug_remove_log_function (gst_debug_log_default) == 1);
#endif
  gst_debug_add_log_function (check_message, NULL);

  count = 0;
  GST_ERROR ("This is an error.");
  ++count;
  GST_WARNING ("This is a warning.");
  ++count;
  GST_INFO ("This is an info message.");
  ++count;
  GST_DEBUG ("This is a debug message.");
  ++count;
  GST_LOG ("This is a log message.");
  ++count;
  GST_CAT_ERROR (cat2, "This is an error with category.");
  ++count;
  GST_CAT_WARNING (cat2, "This is a warning with category.");
  ++count;
  GST_CAT_INFO (cat2, "This is an info message with category.");
  ++count;
  GST_CAT_DEBUG (cat2, "This is a debug message with category.");
  ++count;
  GST_CAT_LOG (cat2, "This is a log message with category.");
  count = -1;
  pipeline = gst_element_factory_make ("pipeline", "testelement");
  count = 10;
  GST_ERROR_OBJECT (pipeline, "This is an error with object.");
  ++count;
  GST_WARNING_OBJECT (pipeline, "This is a warning with object.");
  ++count;
  GST_INFO_OBJECT (pipeline, "This is an info message with object.");
  ++count;
  GST_DEBUG_OBJECT (pipeline, "This is a debug message with object.");
  ++count;
  GST_LOG_OBJECT (pipeline, "This is a log message with object.");
  ++count;
  GST_CAT_ERROR_OBJECT (cat2, pipeline,
      "This is an error with category and object.");
  ++count;
  GST_CAT_WARNING_OBJECT (cat2, pipeline,
      "This is a warning with category and object.");
  ++count;
  GST_CAT_INFO_OBJECT (cat2, pipeline,
      "This is an info message with category and object.");
  ++count;
  GST_CAT_DEBUG_OBJECT (cat2, pipeline,
      "This is a debug message with category and object.");
  ++count;
  GST_CAT_LOG_OBJECT (cat2, pipeline,
      "This is a log message with category and object.");
  count = -1;

#ifndef GST_DISABLE_GST_DEBUG
  g_assert (gst_debug_remove_log_function (check_message) == 1);
#endif

  return 0;
}
Beispiel #10
0
static gboolean
decode_file (const gchar * file, gboolean push_mode)
{
  GstStateChangeReturn state_ret;
  GstElement *sink, *src, *dec, *queue, *pipeline;
  GstMessage *msg;
  GstBus *bus;
  gchar *path;

  pipeline = gst_pipeline_new ("pipeline");
  fail_unless (pipeline != NULL, "Failed to create pipeline!");

  src = gst_element_factory_make ("filesrc", "filesrc");
  fail_unless (src != NULL, "Failed to create filesrc!");

  if (push_mode) {
    queue = gst_element_factory_make ("queue", "queue");
  } else {
    queue = gst_element_factory_make ("identity", "identity");
  }

  dec = gst_element_factory_make ("decodebin", "decodebin");
  fail_unless (dec != NULL, "Failed to create decodebin!");

  sink = gst_element_factory_make ("fakesink", "fakesink");
  fail_unless (sink != NULL, "Failed to create fakesink!");

  bus = gst_element_get_bus (pipeline);

  /* kids, don't use a sync handler for this at home, really; we do because
   * we just want to abort and nothing else */
  gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);

  gst_bin_add_many (GST_BIN (pipeline), src, queue, dec, sink, NULL);
  gst_element_link_many (src, queue, dec, NULL);

  path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
  GST_LOG ("reading file '%s'", path);
  g_object_set (src, "location", path, NULL);

  /* can't link uridecodebin and sink yet, do that later */
  g_signal_connect (dec, "pad-added", G_CALLBACK (pad_added_cb), pipeline);

  state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
  fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);

  if (state_ret == GST_STATE_CHANGE_ASYNC) {
    GST_LOG ("waiting for pipeline to reach PAUSED state");
    state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
    fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
  }

  state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);

  GST_LOG ("PAUSED, let's decode");
  msg = gst_bus_timed_pop_filtered (bus, 10 * GST_SECOND, GST_MESSAGE_EOS);
  GST_LOG ("Done, got EOS message");
  fail_unless (msg != NULL);
  gst_message_unref (msg);
  gst_object_unref (bus);

  fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
      GST_STATE_CHANGE_SUCCESS);
  gst_object_unref (pipeline);

  g_free (path);

  return TRUE;
}
Beispiel #11
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;
}
Beispiel #12
0
GstIsoffParserResult
gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer,
    guint * consumed)
{
  GstIsoffParserResult res = GST_ISOFF_PARSER_OK;
  GstByteReader reader;
  GstMapInfo info;
  gsize remaining;
  guint32 fourcc;

  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
    *consumed = 0;
    return GST_ISOFF_PARSER_ERROR;
  }

  gst_byte_reader_init (&reader, info.data, info.size);

  switch (parser->status) {
    case GST_ISOFF_SIDX_PARSER_INIT:
      if (gst_byte_reader_get_remaining (&reader) < GST_ISOFF_FULL_BOX_SIZE) {
        break;
      }

      parser->size = gst_byte_reader_get_uint32_be_unchecked (&reader);
      fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
      if (fourcc != GST_ISOFF_FOURCC_SIDX) {
        res = GST_ISOFF_PARSER_UNEXPECTED;
        gst_byte_reader_set_pos (&reader, 0);
        break;
      }
      if (parser->size == 1) {
        if (gst_byte_reader_get_remaining (&reader) < 12) {
          gst_byte_reader_set_pos (&reader, 0);
          break;
        }

        parser->size = gst_byte_reader_get_uint64_be_unchecked (&reader);
      }
      if (parser->size == 0) {
        res = GST_ISOFF_PARSER_ERROR;
        gst_byte_reader_set_pos (&reader, 0);
        break;
      }
      parser->sidx.version = gst_byte_reader_get_uint8_unchecked (&reader);
      parser->sidx.flags = gst_byte_reader_get_uint24_le_unchecked (&reader);

      parser->status = GST_ISOFF_SIDX_PARSER_HEADER;

    case GST_ISOFF_SIDX_PARSER_HEADER:
      remaining = gst_byte_reader_get_remaining (&reader);
      if (remaining < 12 + (parser->sidx.version == 0 ? 8 : 16)) {
        break;
      }

      parser->sidx.ref_id = gst_byte_reader_get_uint32_be_unchecked (&reader);
      parser->sidx.timescale =
          gst_byte_reader_get_uint32_be_unchecked (&reader);
      if (parser->sidx.version == 0) {
        parser->sidx.earliest_pts =
            gst_byte_reader_get_uint32_be_unchecked (&reader);
        parser->sidx.first_offset = parser->sidx.earliest_pts =
            gst_byte_reader_get_uint32_be_unchecked (&reader);
      } else {
        parser->sidx.earliest_pts =
            gst_byte_reader_get_uint64_be_unchecked (&reader);
        parser->sidx.first_offset =
            gst_byte_reader_get_uint64_be_unchecked (&reader);
      }
      /* skip 2 reserved bytes */
      gst_byte_reader_skip_unchecked (&reader, 2);
      parser->sidx.entries_count =
          gst_byte_reader_get_uint16_be_unchecked (&reader);

      GST_LOG ("Timescale: %" G_GUINT32_FORMAT, parser->sidx.timescale);
      GST_LOG ("Earliest pts: %" G_GUINT64_FORMAT, parser->sidx.earliest_pts);
      GST_LOG ("First offset: %" G_GUINT64_FORMAT, parser->sidx.first_offset);

      parser->cumulative_pts =
          gst_util_uint64_scale_int_round (parser->sidx.earliest_pts,
          GST_SECOND, parser->sidx.timescale);

      if (parser->sidx.entries_count) {
        parser->sidx.entries =
            g_malloc (sizeof (GstSidxBoxEntry) * parser->sidx.entries_count);
      }
      parser->sidx.entry_index = 0;

      parser->status = GST_ISOFF_SIDX_PARSER_DATA;

    case GST_ISOFF_SIDX_PARSER_DATA:
      while (parser->sidx.entry_index < parser->sidx.entries_count) {
        GstSidxBoxEntry *entry =
            &parser->sidx.entries[parser->sidx.entry_index];

        remaining = gst_byte_reader_get_remaining (&reader);;
        if (remaining < 12)
          break;

        entry->offset = parser->cumulative_entry_size;
        entry->pts = parser->cumulative_pts;
        gst_isoff_parse_sidx_entry (entry, &reader);
        entry->duration = gst_util_uint64_scale_int_round (entry->duration,
            GST_SECOND, parser->sidx.timescale);
        parser->cumulative_entry_size += entry->size;
        parser->cumulative_pts += entry->duration;

        GST_LOG ("Sidx entry %d) offset: %" G_GUINT64_FORMAT ", pts: %"
            GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT " - size %"
            G_GUINT32_FORMAT, parser->sidx.entry_index, entry->offset,
            GST_TIME_ARGS (entry->pts), GST_TIME_ARGS (entry->duration),
            entry->size);

        parser->sidx.entry_index++;
      }

      if (parser->sidx.entry_index == parser->sidx.entries_count)
        parser->status = GST_ISOFF_SIDX_PARSER_FINISHED;
      else
        break;
    case GST_ISOFF_SIDX_PARSER_FINISHED:
      parser->sidx.entry_index = 0;
      res = GST_ISOFF_PARSER_DONE;
      break;
  }

  *consumed = gst_byte_reader_get_pos (&reader);
  gst_buffer_unmap (buffer, &info);
  return res;
}
Beispiel #13
0
static void
process_file (const gchar * file, gboolean push_mode, gint repeat,
    gint num_buffers)
{
  GstElement *src, *sep, *sink, *flvdemux, *pipeline;
  GstBus *bus;
  gchar *path;
  gint counter;

  pipeline = gst_pipeline_new ("pipeline");
  fail_unless (pipeline != NULL, "Failed to create pipeline!");

  bus = gst_element_get_bus (pipeline);

  /* kids, don't use a sync handler for this at home, really; we do because
   * we just want to abort and nothing else */
  gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);

  src = gst_element_factory_make ("filesrc", "filesrc");
  fail_unless (src != NULL, "Failed to create 'filesrc' element!");

  if (push_mode) {
    sep = gst_element_factory_make ("queue", "queue");
    fail_unless (sep != NULL, "Failed to create 'queue' element");
  } else {
    sep = gst_element_factory_make ("identity", "identity");
    fail_unless (sep != NULL, "Failed to create 'identity' element");
  }

  flvdemux = gst_element_factory_make ("flvdemux", "flvdemux");
  fail_unless (flvdemux != NULL, "Failed to create 'flvdemux' element!");

  sink = gst_element_factory_make ("fakesink", "fakesink");
  fail_unless (sink != NULL, "Failed to create 'fakesink' element!");

  g_object_set (sink, "signal-handoffs", TRUE, NULL);
  g_signal_connect (sink, "handoff", G_CALLBACK (handoff_cb), &counter);

  gst_bin_add_many (GST_BIN (pipeline), src, sep, flvdemux, sink, NULL);

  fail_unless (gst_element_link (src, sep));
  fail_unless (gst_element_link (sep, flvdemux));

  /* can't link flvdemux and sink yet, do that later */
  g_signal_connect (flvdemux, "pad-added", G_CALLBACK (pad_added_cb), pipeline);

  path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
  GST_LOG ("processing file '%s'", path);
  g_object_set (src, "location", path, NULL);

  do {
    GstStateChangeReturn state_ret;
    GstMessage *msg;

    GST_LOG ("repeat=%d", repeat);

    counter = 0;

    state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
    fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);

    if (state_ret == GST_STATE_CHANGE_ASYNC) {
      GST_LOG ("waiting for pipeline to reach PAUSED state");
      state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
      fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
    }

    GST_LOG ("PAUSED, let's read all of it");

    state_ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
    fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);

    msg = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
    fail_unless (msg != NULL, "Expected EOS message on bus! (%s)", file);

    gst_message_unref (msg);

    if (num_buffers >= 0) {
      fail_unless_equals_int (counter, num_buffers);
    }

    fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
        GST_STATE_CHANGE_SUCCESS);

    --repeat;
  } while (repeat > 0);

  gst_object_unref (bus);
  gst_object_unref (pipeline);

  g_free (path);
}
/**
 * parse_encoding_profile:
 * @in: a #GKeyFile
 * @parentprofilename: the parent profile name (including 'profile-' or 'streamprofile-' header)
 * @profilename: the profile name group to parse
 * @nbgroups: the number of top-level groups
 * @groups: the top-level groups
 */
static GstEncodingProfile *
parse_encoding_profile (GKeyFile * in, gchar * parentprofilename,
    gchar * profilename, gsize nbgroups, gchar ** groups)
{
  GstEncodingProfile *sprof = NULL;
  gchar **parent;
  gchar *proftype, *format, *preset, *restriction, *pname, *description,
      *locale;
  GstCaps *formatcaps = NULL;
  GstCaps *restrictioncaps = NULL;
  gboolean variableframerate;
  gint pass, presence;
  gsize i, nbencprofiles;

  GST_DEBUG ("parentprofilename : %s , profilename : %s",
      parentprofilename, profilename);

  if (parentprofilename) {
    gboolean found = FALSE;

    parent =
        g_key_file_get_string_list (in, profilename, "parent",
        &nbencprofiles, NULL);
    if (!parent || !nbencprofiles) {
      return NULL;
    }

    /* Check if this streamprofile is used in <profilename> */
    for (i = 0; i < nbencprofiles; i++) {
      if (!g_strcmp0 (parent[i], parentprofilename)) {
        found = TRUE;
        break;
      }
    }
    g_strfreev (parent);

    if (!found) {
      GST_DEBUG ("Stream profile '%s' isn't used in profile '%s'",
          profilename, parentprofilename);
      return NULL;
    }
  }

  pname = g_key_file_get_value (in, profilename, "name", NULL);

  locale = get_locale ();
  /* will try to fall back to untranslated string if no translation found */
  description = g_key_file_get_locale_string (in, profilename,
      "description", locale, NULL);
  g_free (locale);

  /* Note: a missing description is normal for non-container profiles */
  if (description == NULL) {
    GST_LOG ("Missing 'description' field for streamprofile %s", profilename);
  }

  /* Parse the remaining fields */
  proftype = g_key_file_get_value (in, profilename, "type", NULL);
  if (!proftype) {
    GST_WARNING ("Missing 'type' field for streamprofile %s", profilename);
    return NULL;
  }

  format = g_key_file_get_value (in, profilename, "format", NULL);
  if (format) {
    formatcaps = gst_caps_from_string (format);
    g_free (format);
  }

  preset = g_key_file_get_value (in, profilename, "preset", NULL);

  restriction = g_key_file_get_value (in, profilename, "restriction", NULL);
  if (restriction) {
    restrictioncaps = gst_caps_from_string (restriction);
    g_free (restriction);
  }

  presence = g_key_file_get_integer (in, profilename, "presence", NULL);
  pass = g_key_file_get_integer (in, profilename, "pass", NULL);
  variableframerate =
      g_key_file_get_boolean (in, profilename, "variableframerate", NULL);

  /* Build the streamprofile ! */
  if (!g_strcmp0 (proftype, "container")) {
    GstEncodingProfile *pprof;

    sprof =
        (GstEncodingProfile *) gst_encoding_container_profile_new (pname,
        description, formatcaps, preset);
    /* Now look for the stream profiles */
    for (i = 0; i < nbgroups; i++) {
      if (!g_ascii_strncasecmp (groups[i], "streamprofile-", 13)) {
        pprof = parse_encoding_profile (in, pname, groups[i], nbgroups, groups);
        if (pprof) {
          gst_encoding_container_profile_add_profile (
              (GstEncodingContainerProfile *) sprof, pprof);
        }
      }
    }
  } else if (!g_strcmp0 (proftype, "video")) {
    sprof =
        (GstEncodingProfile *) gst_encoding_video_profile_new (formatcaps,
        preset, restrictioncaps, presence);
    gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile
            *) sprof, variableframerate);
    gst_encoding_video_profile_set_pass ((GstEncodingVideoProfile *) sprof,
        pass);
    gst_encoding_profile_set_name (sprof, pname);
    gst_encoding_profile_set_description (sprof, description);
  } else if (!g_strcmp0 (proftype, "audio")) {
    sprof =
        (GstEncodingProfile *) gst_encoding_audio_profile_new (formatcaps,
        preset, restrictioncaps, presence);
    gst_encoding_profile_set_name (sprof, pname);
    gst_encoding_profile_set_description (sprof, description);
  } else
    GST_ERROR ("Unknown profile format '%s'", proftype);

  if (restrictioncaps)
    gst_caps_unref (restrictioncaps);
  if (formatcaps)
    gst_caps_unref (formatcaps);

  g_free (pname);
  g_free (description);
  g_free (preset);
  g_free (proftype);

  return sprof;
}
/**
 * gst_missing_plugin_message_get_description:
 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
 *
 * Returns a localised string describing the missing feature, for use in
 * error dialogs and the like. Should never return NULL unless @msg is not
 * a valid missing-plugin message.
 *
 * This function is mainly for applications that need a human-readable string
 * describing a missing plugin, given a previously collected missing-plugin
 * message
 *
 * Returns: a newly-allocated description string, or NULL on error. Free
 *          string with g_free() when not needed any longer.
 */
gchar *
gst_missing_plugin_message_get_description (GstMessage * msg)
{
  GstMissingType missing_type;
  const gchar *desc;
  gchar *ret = NULL;

  g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);

  GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure);

  desc = gst_structure_get_string (msg->structure, "name");
  if (desc != NULL && *desc != '\0') {
    ret = g_strdup (desc);
    goto done;
  }

  /* fallback #1 */
  missing_type = missing_structure_get_type (msg->structure);

  switch (missing_type) {
    case GST_MISSING_TYPE_URISOURCE:
    case GST_MISSING_TYPE_URISINK:
    case GST_MISSING_TYPE_ELEMENT:{
      gchar *detail = NULL;

      if (missing_structure_get_string_detail (msg->structure, &detail)) {
        if (missing_type == GST_MISSING_TYPE_URISOURCE)
          ret = gst_pb_utils_get_source_description (detail);
        else if (missing_type == GST_MISSING_TYPE_URISINK)
          ret = gst_pb_utils_get_sink_description (detail);
        else
          ret = gst_pb_utils_get_sink_description (detail);
        g_free (detail);
      }
      break;
    }
    case GST_MISSING_TYPE_DECODER:
    case GST_MISSING_TYPE_ENCODER:{
      GstCaps *caps = NULL;

      if (missing_structure_get_caps_detail (msg->structure, &caps)) {
        if (missing_type == GST_MISSING_TYPE_DECODER)
          ret = gst_pb_utils_get_decoder_description (caps);
        else
          ret = gst_pb_utils_get_encoder_description (caps);
        gst_caps_unref (caps);
      }
      break;
    }
    default:
      break;
  }

  if (ret)
    goto done;

  /* fallback #2 */
  switch (missing_type) {
    case GST_MISSING_TYPE_URISOURCE:
      desc = _("Unknown source element");
      break;
    case GST_MISSING_TYPE_URISINK:
      desc = _("Unknown sink element");
      break;
    case GST_MISSING_TYPE_ELEMENT:
      desc = _("Unknown element");
      break;
    case GST_MISSING_TYPE_DECODER:
      desc = _("Unknown decoder element");
      break;
    case GST_MISSING_TYPE_ENCODER:
      desc = _("Unknown encoder element");
      break;
    default:
      /* we should really never get here, but we better still return
       * something if we do */
      desc = _("Plugin or element of unknown type");
      break;
  }
  ret = g_strdup (desc);

done:

  GST_LOG ("returning '%s'", ret);
  return ret;
}
Beispiel #16
0
static void
check_pad_template (GstPadTemplate * tmpl)
{
  const GValue *list_val, *fmt_val;
  GstStructure *s;
  gboolean *formats_supported;
  GstCaps *caps;
  guint i, num_formats;

  num_formats = get_num_formats ();
  formats_supported = g_new0 (gboolean, num_formats);

  caps = gst_pad_template_get_caps (tmpl);

  /* If this fails, we need to update this unit test */
  fail_unless_equals_int (gst_caps_get_size (caps), 2);
  /* Remove the ANY caps features structure */
  caps = gst_caps_truncate (caps);
  s = gst_caps_get_structure (caps, 0);

  fail_unless (gst_structure_has_name (s, "video/x-raw"));

  list_val = gst_structure_get_value (s, "format");
  fail_unless (list_val != NULL);
  /* If this fails, we need to update this unit test */
  fail_unless (GST_VALUE_HOLDS_LIST (list_val));

  for (i = 0; i < gst_value_list_get_size (list_val); ++i) {
    GstVideoFormat fmt;
    const gchar *fmt_str;

    fmt_val = gst_value_list_get_value (list_val, i);
    fail_unless (G_VALUE_HOLDS_STRING (fmt_val));
    fmt_str = g_value_get_string (fmt_val);
    GST_LOG ("format string: '%s'", fmt_str);
    fmt = gst_video_format_from_string (fmt_str);
    if (fmt == GST_VIDEO_FORMAT_UNKNOWN)
      g_error ("Unknown raw format '%s' in pad template caps", fmt_str);
    formats_supported[(guint) fmt] = TRUE;
  }

  gst_caps_unref (caps);

  for (i = 2; i < num_formats; ++i) {
    if (!formats_supported[i]) {
      const gchar *fmt_str = gst_video_format_to_string ((GstVideoFormat) i);

      switch (i) {
        case GST_VIDEO_FORMAT_v210:
        case GST_VIDEO_FORMAT_v216:
        case GST_VIDEO_FORMAT_NV12:
        case GST_VIDEO_FORMAT_NV16:
        case GST_VIDEO_FORMAT_NV21:
        case GST_VIDEO_FORMAT_NV24:
        case GST_VIDEO_FORMAT_UYVP:
        case GST_VIDEO_FORMAT_A420:
        case GST_VIDEO_FORMAT_YUV9:
        case GST_VIDEO_FORMAT_YVU9:
        case GST_VIDEO_FORMAT_IYU1:
        case GST_VIDEO_FORMAT_r210:{
          static gboolean shown_fixme[100] = { FALSE, };

          if (!shown_fixme[i]) {
            GST_FIXME ("FIXME: add %s support to videoscale", fmt_str);
            shown_fixme[i] = TRUE;
          }
          break;
        }
        case GST_VIDEO_FORMAT_BGR16:
        case GST_VIDEO_FORMAT_BGR15:
        case GST_VIDEO_FORMAT_RGB8P:
        case GST_VIDEO_FORMAT_I420_10BE:
        case GST_VIDEO_FORMAT_I420_10LE:
        case GST_VIDEO_FORMAT_I422_10BE:
        case GST_VIDEO_FORMAT_I422_10LE:
        case GST_VIDEO_FORMAT_Y444_10BE:
        case GST_VIDEO_FORMAT_Y444_10LE:
        case GST_VIDEO_FORMAT_GBR:
        case GST_VIDEO_FORMAT_GBR_10BE:
        case GST_VIDEO_FORMAT_GBR_10LE:
          GST_LOG ("Ignoring lack of support for format %s", fmt_str);
          break;
        default:
          g_error ("videoscale doesn't support format '%s'", fmt_str);
          break;
      }
    }
  }

  g_free (formats_supported);
}
Beispiel #17
0
static GstFlowReturn
mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstFlowReturn res = GST_FLOW_OK;
  MpegTSBase *base;
  MpegTSPacketizerPacketReturn pret;
  MpegTSPacketizer2 *packetizer;
  MpegTSPacketizerPacket packet;
  MpegTSBaseClass *klass;

  base = GST_MPEGTS_BASE (parent);
  klass = GST_MPEGTS_BASE_GET_CLASS (base);

  packetizer = base->packetizer;

  if (klass->input_done)
    gst_buffer_ref (buf);

  if (GST_BUFFER_IS_DISCONT (buf)) {
    GST_DEBUG_OBJECT (base, "Got DISCONT buffer, flushing");
    res = mpegts_base_drain (base);
    if (G_UNLIKELY (res != GST_FLOW_OK))
      return res;

    mpegts_base_flush (base, FALSE);
    /* In the case of discontinuities in push-mode with TIME segment
     * we want to drop all previous observations (hard:TRUE) from
     * the packetizer */
    if (base->mode == BASE_MODE_PUSHING
        && base->segment.format == GST_FORMAT_TIME)
      mpegts_packetizer_flush (base->packetizer, TRUE);
    else
      mpegts_packetizer_flush (base->packetizer, FALSE);
  }

  mpegts_packetizer_push (base->packetizer, buf);

  while (res == GST_FLOW_OK) {
    pret = mpegts_packetizer_next_packet (base->packetizer, &packet);

    /* If we don't have enough data, return */
    if (G_UNLIKELY (pret == PACKET_NEED_MORE))
      break;

    if (G_UNLIKELY (pret == PACKET_BAD)) {
      /* bad header, skip the packet */
      GST_DEBUG_OBJECT (base, "bad packet, skipping");
      goto next;
    }

    if (klass->inspect_packet)
      klass->inspect_packet (base, &packet);

    /* If it's a known PES, push it */
    if (MPEGTS_BIT_IS_SET (base->is_pes, packet.pid)) {
      /* push the packet downstream */
      if (base->push_data)
        res = klass->push (base, &packet, NULL);
    } else if (packet.payload
        && MPEGTS_BIT_IS_SET (base->known_psi, packet.pid)) {
      /* base PSI data */
      GList *others, *tmp;
      GstMpegtsSection *section;

      section = mpegts_packetizer_push_section (packetizer, &packet, &others);
      if (section)
        mpegts_base_handle_psi (base, section);
      if (G_UNLIKELY (others)) {
        for (tmp = others; tmp; tmp = tmp->next)
          mpegts_base_handle_psi (base, (GstMpegtsSection *) tmp->data);
        g_list_free (others);
      }

      /* we need to push section packet downstream */
      if (base->push_section)
        res = klass->push (base, &packet, section);

    } else if (packet.payload && packet.pid != 0x1fff)
      GST_LOG ("PID 0x%04x Saw packet on a pid we don't handle", packet.pid);

  next:
    mpegts_packetizer_clear_packet (base->packetizer, &packet);
  }

  if (klass->input_done) {
    if (res == GST_FLOW_OK)
      res = klass->input_done (base, buf);
    else
      gst_buffer_unref (buf);
  }

  return res;
}
Beispiel #18
0
static GstBuffer *
read_device (int fd, int adapter_number, int frontend_number, int size,
    GstDvbSrc * object)
{
  int count = 0;
  struct pollfd pfd[1];
  int ret_val = 0;
  guint attempts = 0;
  const int TIMEOUT = 100;

  GstBuffer *buf = gst_buffer_new_and_alloc (size);

  g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);

  if (fd < 0) {
    return NULL;
  }

  pfd[0].fd = fd;
  pfd[0].events = POLLIN;

  while (count < size && !object->need_unlock) {
    ret_val = poll (pfd, 1, TIMEOUT);
    if (ret_val > 0) {
      if (pfd[0].revents & POLLIN) {
        int tmp = 0;

        tmp = read (fd, GST_BUFFER_DATA (buf) + count, size - count);
        if (tmp < 0) {
          GST_WARNING
              ("Unable to read from device: /dev/dvb/adapter%d/dvr%d (%d)",
              adapter_number, frontend_number, errno);
          attempts += 1;
          if (attempts % 10 == 0) {
            GST_WARNING
                ("Unable to read from device after %u attempts: /dev/dvb/adapter%d/dvr%d",
                attempts, adapter_number, frontend_number);
          }

        } else
          count = count + tmp;
      } else {
        GST_LOG ("revents = %d\n", pfd[0].revents);
      }
    } else if (ret_val == 0) {  // poll timeout
      attempts += 1;
      GST_INFO ("Reading from device /dev/dvb/adapter%d/dvr%d timedout (%d)",
          adapter_number, frontend_number, attempts);

      if (attempts % 10 == 0) {
        GST_WARNING
            ("Unable to read after %u attempts from device: /dev/dvb/adapter%d/dvr%d (%d)",
            attempts, adapter_number, frontend_number, errno);
        gst_element_post_message (GST_ELEMENT_CAST (object),
            gst_message_new_element (GST_OBJECT (object),
                gst_structure_empty_new ("dvb-read-failure")));

      }
    } else if (errno == -EINTR) {       // poll interrupted
      if (attempts % 50 == 0) {
        gst_buffer_unref (buf);
        return NULL;
      };
    }

  }

  if (!count) {
    gst_buffer_unref (buf);
    return NULL;
  }

  GST_BUFFER_SIZE (buf) = count;
  GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE;
  return buf;
}
/*
 * 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;
  guint todo;
  GstGnomeVFSSrc *src;

  src = GST_GNOME_VFS_SRC (basesrc);

  GST_DEBUG ("now at %" G_GINT64_FORMAT ", reading from %" G_GUINT64_FORMAT
      ", 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 %" G_GUINT64_FORMAT, 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_try_new_and_alloc (size);
  if (G_UNLIKELY (buf == NULL)) {
    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size);
    return GST_FLOW_ERROR;
  }

  data = GST_BUFFER_DATA (buf);

  todo = size;
  while (todo > 0) {
    /* this can return less that we ask for */
    res = gnome_vfs_read (src->handle, data, todo, &readbytes);

    if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK
                && readbytes == 0)))
      goto eos;

    if (G_UNLIKELY (res != GNOME_VFS_OK))
      goto read_failed;

    if (readbytes < todo) {
      data = &data[readbytes];
      todo -= readbytes;
    } else {
      todo = 0;
    }
    GST_LOG ("  got size %" G_GUINT64_FORMAT, readbytes);
  }
  GST_BUFFER_OFFSET (buf) = src->curoffset;
  src->curoffset += size;

  /* 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;
  }
}
Beispiel #20
0
/**
 * gst_video_info_align:
 * @info: a #GstVideoInfo
 * @align: alignment parameters
 *
 * Adjust the offset and stride fields in @info so that the padding and
 * stride alignment in @align is respected.
 *
 * Extra padding will be added to the right side when stride alignment padding
 * is required and @align will be updated with the new padding values.
 */
void
gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
{
  const GstVideoFormatInfo *vinfo = info->finfo;
  gint width, height;
  gint padded_width, padded_height;
  gint i, n_planes;
  gboolean aligned;

  width = GST_VIDEO_INFO_WIDTH (info);
  height = GST_VIDEO_INFO_HEIGHT (info);

  GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
      align->padding_left, align->padding_right, align->padding_bottom);

  n_planes = GST_VIDEO_INFO_N_PLANES (info);

  if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
    n_planes--;

  /* first make sure the left padding does not cause alignment problems later */
  do {
    GST_LOG ("left padding %u", align->padding_left);
    aligned = TRUE;
    for (i = 0; i < n_planes; i++) {
      gint hedge;

      /* this is the amout of pixels to add as left padding */
      hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
      hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);

      GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
          align->stride_align[i]);
      aligned &= (hedge & align->stride_align[i]) == 0;
    }
    if (aligned)
      break;

    GST_LOG ("unaligned padding, increasing padding");
    /* increase padded_width */
    align->padding_left += align->padding_left & ~(align->padding_left - 1);
  } while (!aligned);

  /* add the padding */
  padded_width = width + align->padding_left + align->padding_right;
  padded_height = height + align->padding_top + align->padding_bottom;

  do {
    GST_LOG ("padded dimension %u-%u", padded_width, padded_height);

    info->width = padded_width;
    info->height = padded_height;
    fill_planes (info);

    /* check alignment */
    aligned = TRUE;
    for (i = 0; i < n_planes; i++) {
      GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
          align->stride_align[i]);
      aligned &= (info->stride[i] & align->stride_align[i]) == 0;
    }
    if (aligned)
      break;

    GST_LOG ("unaligned strides, increasing dimension");
    /* increase padded_width */
    padded_width += padded_width & ~(padded_width - 1);
  } while (!aligned);

  align->padding_right = padded_width - width - align->padding_left;

  info->width = width;
  info->height = height;

  for (i = 0; i < n_planes; i++) {
    gint vedge, hedge, comp;

    /* Find the component for this plane, FIXME, we assume the plane number and
     * component number is the same for now, for scaling the dimensions this is
     * currently true for all formats but it might not be when adding new
     * formats. We might need to add a plane subsamling in the format info to
     * make this more generic or maybe use a plane -> component mapping. */
    comp = i;

    hedge =
        GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
    vedge =
        GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);

    GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
        comp, hedge, vedge, align->stride_align[i], info->stride[i]);

    info->offset[i] += (vedge * info->stride[i]) +
        (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));
  }
}
Beispiel #21
0
/* make sure our script gets called with the right parameters */
static void
test_pb_utils_install_plugins_do_callout (const gchar * const *details,
    GstInstallPluginsContext * ctx, const gchar * script,
    GstInstallPluginsReturn expected_result)
{
#ifdef G_OS_UNIX
  GstInstallPluginsReturn ret;
  GError *err = NULL;
  gchar *path;

  path = g_strdup_printf ("%s/gst-plugins-base-unit-test-helper.%s.%lu",
      g_get_tmp_dir (), (g_get_user_name ())? g_get_user_name () : "nobody",
      (gulong) getpid ());

  if (!g_file_set_contents (path, script, -1, &err)) {
    GST_DEBUG ("Failed to write test script to %s: %s", path, err->message);
    g_error_free (err);
    goto done;
  }

  if (chmod (path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
    GST_DEBUG ("Could not set mode u+rwx on '%s'", path);
    goto done;
  }

  /* test gst_install_plugins_supported() I */
  g_setenv ("GST_INSTALL_PLUGINS_HELPER", "/i/do/not/ex.ist!", 1);
  fail_if (gst_install_plugins_supported ());

  GST_LOG ("setting GST_INSTALL_PLUGINS_HELPER to '%s'", path);
  g_setenv ("GST_INSTALL_PLUGINS_HELPER", path, 1);

  /* test gst_install_plugins_supported() II */
  fail_unless (gst_install_plugins_supported ());

  /* test sync callout */
  ret = gst_install_plugins_sync (details, ctx);
  fail_unless (ret == GST_INSTALL_PLUGINS_HELPER_MISSING ||
      ret == expected_result,
      "gst_install_plugins_sync() failed with unexpected ret %d, which is "
      "neither HELPER_MISSING nor %d", ret, expected_result);

  /* test async callout */
  marker = -333;
  ret = gst_install_plugins_async (details, ctx, result_cb,
      (gpointer) & marker);
  fail_unless (ret == GST_INSTALL_PLUGINS_HELPER_MISSING ||
      ret == GST_INSTALL_PLUGINS_STARTED_OK,
      "gst_install_plugins_async() failed with unexpected ret %d", ret);
  if (ret == GST_INSTALL_PLUGINS_STARTED_OK) {
    while (marker == -333) {
      g_usleep (500);
      g_main_context_iteration (NULL, FALSE);
    }
    /* and check that the callback was called with the expected code */
    fail_unless_equals_int (marker, expected_result);
  }

done:

  unlink (path);
  g_free (path);
#endif /* G_OS_UNIX */
}
/* Note: lots of this code here is also in the videotestsrc.c unit test */
void  test_rgb_to_rgb()
{
  const struct
  {
    const gchar *pattern_name;
    gint pattern_enum;
    guint8 r_expected;
    guint8 g_expected;
    guint8 b_expected;
  } test_patterns[] = {
    {
    "white", 3, 0xff, 0xff, 0xff}, {
    "red", 4, 0xff, 0x00, 0x00}, {
    "green", 5, 0x00, 0xff, 0x00}, {
    "blue", 6, 0x00, 0x00, 0xff}, {
    "black", 2, 0x00, 0x00, 0x00}
  };
  GstElement *pipeline, *src, *filter1, *csp, *filter2, *sink;
  const GstCaps *template_caps;
  GstBuffer *buf = NULL;
  GstPad *srcpad;
  GList *conversions, *l;
  gint p;

  /* test check function */
  fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22);

  pipeline = gst_pipeline_new ("pipeline");
  src = gst_check_setup_element ("videotestsrc");
  filter1 = gst_check_setup_element ("capsfilter");
  csp = gst_check_setup_element ("ffmpegcolorspace");
  filter2 = gst_element_factory_make ("capsfilter", "to_filter");
  sink = gst_check_setup_element ("fakesink");

  gst_bin_add_many (GST_BIN (pipeline), src, filter1, csp, filter2, sink, NULL);

  fail_unless (gst_element_link (src, filter1));
  fail_unless (gst_element_link (filter1, csp));
  fail_unless (gst_element_link (csp, filter2));
  fail_unless (gst_element_link (filter2, sink));

  srcpad = gst_element_get_pad (src, "src");
  template_caps = gst_pad_get_pad_template_caps (srcpad);
  gst_object_unref (srcpad);

  g_object_set (sink, "signal-handoffs", TRUE, NULL);
  g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &buf);

  GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps);

  conversions = create_rgb_conversions ();

  for (l = conversions; l != NULL; l = l->next) {
    RGBConversion *conv = (RGBConversion *) l->data;

    /* does videotestsrc support the from_caps? */
    if (!gst_caps_is_subset (conv->from_caps, template_caps)) {
      GST_DEBUG ("videotestsrc doesn't support from_caps %" GST_PTR_FORMAT,
          conv->from_caps);
      continue;
    }

    /* caps are supported, let's run some tests then ... */
    for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) {
      GstStateChangeReturn state_ret;
      RGBFormat *from = &conv->from_fmt;
      RGBFormat *to = &conv->to_fmt;

      /* trick compiler into thinking from is used, might throw warning
       * otherwise if the debugging system is disabled */
      fail_unless (from != NULL);

      gst_element_set_state (pipeline, GST_STATE_NULL);

      g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL);

      GST_INFO ("%5s %u/%u %08x %08x %08x %08x %u => "
          "%5s %u/%u %08x %08x %08x %08x %u, pattern=%s",
          from->nick, from->bpp, from->depth, from->red_mask,
          from->green_mask, from->blue_mask, from->alpha_mask,
          from->endianness, to->nick, to->bpp, to->depth, to->red_mask,
          to->green_mask, to->blue_mask, to->alpha_mask, to->endianness,
          test_patterns[p].pattern_name);

      /* now get videotestsrc to produce a buffer with the given caps */
      g_object_set (filter1, "caps", conv->from_caps, NULL);

      /* ... and force ffmpegcolorspace to convert to our target caps */
      g_object_set (filter2, "caps", conv->to_caps, NULL);

      state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
      if (state_ret == GST_STATE_CHANGE_FAILURE) {
        GstMessage *msg;
        GError *err = NULL;

        msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_ERROR, 0);
        fail_if (msg == NULL, "expected ERROR message on the bus");
        fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);
        gst_message_parse_error (msg, &err, NULL);
        fail_unless (err != NULL);
        if (msg->src == GST_OBJECT_CAST (src) &&
            err->code == GST_STREAM_ERROR_FORMAT) {
          GST_DEBUG ("ffmpegcolorspace does not support this conversion");
          gst_message_unref (msg);
          g_error_free (err);
          continue;
        }
        fail_unless (state_ret != GST_STATE_CHANGE_FAILURE,
            "pipeline _set_state() to PAUSED failed: %s", err->message);
      }

      state_ret = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
     fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS,
          "pipeline failed going to PAUSED state");

      state_ret = gst_element_set_state (pipeline, GST_STATE_NULL);
     fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS);

      fail_unless (buf != NULL);

      /* check buffer caps */
      {
        GstStructure *s;
        gint v;

        fail_unless (GST_BUFFER_CAPS (buf) != NULL);
        s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0);
        fail_unless (gst_structure_get_int (s, "bpp", &v));
        fail_unless_equals_int (v, to->bpp);
        fail_unless (gst_structure_get_int (s, "depth", &v));
        fail_unless_equals_int (v, to->depth);
        fail_unless (gst_structure_get_int (s, "red_mask", &v));
        fail_unless_equals_int (v, to->red_mask);
        fail_unless (gst_structure_get_int (s, "green_mask", &v));
        fail_unless_equals_int (v, to->green_mask);
        fail_unless (gst_structure_get_int (s, "blue_mask", &v));
        fail_unless_equals_int (v, to->blue_mask);
        /* there mustn't be an alpha_mask if there's no alpha component */
        if (to->depth == 32) {
          fail_unless (gst_structure_get_int (s, "alpha_mask", &v));
          fail_unless_equals_int (v, to->alpha_mask);
        } else {
          fail_unless (gst_structure_get_value (s, "alpha_mask") == NULL);
        }
      }

      /* now check the top-left pixel */
      check_rgb_buf (GST_BUFFER_DATA (buf), to->red_mask,
          to->green_mask, to->blue_mask, to->alpha_mask,
          test_patterns[p].r_expected, test_patterns[p].g_expected,
          test_patterns[p].b_expected, to->endianness, to->bpp, to->depth);

      gst_buffer_unref (buf);
      buf = NULL;
    }
  }

  g_list_foreach (conversions, (GFunc) rgb_conversion_free, NULL);
  g_list_free (conversions);

  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  std_log(LOG_FILENAME_LINE, "Test Successful");
  create_xml(0);
}
static gboolean
gst_raw_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstRawParse *rp = GST_RAW_PARSE (parent);
  gboolean ret = FALSE;

  GST_DEBUG ("src_query %s", gst_query_type_get_name (GST_QUERY_TYPE (query)));

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:
    {
      GstFormat format;
      gint64 time, value;

      GST_LOG ("query position");

      gst_query_parse_position (query, &format, NULL);

      time = rp->segment.position;
      ret = gst_raw_parse_convert (rp, GST_FORMAT_TIME, time, format, &value);

      gst_query_set_position (query, format, value);

      break;
    }
    case GST_QUERY_DURATION:{
      gint64 duration;
      GstFormat format;
      GstQuery *bquery;

      GST_LOG ("query duration");
      ret = gst_pad_peer_query (rp->sinkpad, query);
      if (ret)
        goto done;

      gst_query_parse_duration (query, &format, NULL);
      /* We only handle TIME and DEFAULT format */
      if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT)
        goto error;

      bquery = gst_query_new_duration (GST_FORMAT_BYTES);
      ret = gst_pad_peer_query (rp->sinkpad, bquery);
      if (!ret) {
        gst_query_unref (bquery);
        goto error;
      }

      gst_query_parse_duration (bquery, NULL, &duration);
      gst_query_unref (bquery);

      ret =
          gst_raw_parse_convert (rp, GST_FORMAT_BYTES, duration, format,
          &duration);
      if (ret)
        gst_query_set_duration (query, format, duration);

      break;
    }
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      GST_LOG ("query convert");

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      ret = gst_raw_parse_convert (rp, src_fmt, src_val, dest_fmt, &dest_val);
      if (!ret)
        goto error;
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
      break;
    }
    case GST_QUERY_SEEKING:{
      GstFormat fmt;

      ret = TRUE;
      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
      if (fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT
          && fmt != GST_FORMAT_BYTES) {
        gst_query_set_seeking (query, fmt, FALSE, -1, -1);
      } else if (rp->mode == GST_PAD_MODE_PUSH) {
        GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
        gboolean seekable;

        seekable = gst_pad_peer_query (rp->sinkpad, peerquery);
        if (seekable)
          gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);

        gst_query_unref (peerquery);
        gst_query_set_seeking (query, fmt, seekable, seekable ? 0 : -1, -1);
      } else {
        gst_query_set_seeking (query, fmt, TRUE, 0, -1);
      }
      break;
    }
    default:
      /* else forward upstream */
      ret = gst_pad_query_default (rp->sinkpad, parent, query);
      break;
  }

done:
  return ret;

  /* ERRORS */
error:
  {
    GST_DEBUG_OBJECT (rp, "query failed");
    goto done;
  }
}
static gboolean
gst_gl_context_glx_create_context (GstGLContext * context,
    GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
  GstGLContextGLX *context_glx;
  GstGLWindow *window;
  GstGLWindowX11 *window_x11;
  GstGLDisplay *display = NULL;
  gboolean create_context;
  const char *glx_exts;
  Display *device;
  guintptr external_gl_context = 0;

  context_glx = GST_GL_CONTEXT_GLX (context);
  window = gst_gl_context_get_window (context);

  if (!GST_IS_GL_WINDOW_X11 (window)) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
        "Cannot create an GLX context from a non-X11 window");
    goto failure;
  }

  window_x11 = GST_GL_WINDOW_X11 (window);
  display = gst_gl_context_get_display (context);

  if (other_context) {
    if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_GLX) {
      g_set_error (error, GST_GL_CONTEXT_ERROR,
          GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
          "Cannot share context with non-GLX context");
      goto failure;
    }

    external_gl_context = gst_gl_context_get_gl_context (other_context);
  }

  device = (Display *) gst_gl_display_get_handle (display);
  if (!device) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, "Invalid Display handle");
    goto failure;
  }

  glx_exts = glXQueryExtensionsString (device, DefaultScreen (device));

  create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts);
  context_glx->priv->glXCreateContextAttribsARB =
      (gpointer) glXGetProcAddressARB ((const GLubyte *)
      "glXCreateContextAttribsARB");

  if (!context_glx->glx_context && gl_api & GST_GL_API_OPENGL3 && create_context
      && context_glx->priv->glXCreateContextAttribsARB) {
    gint i;

    for (i = 0; i < G_N_ELEMENTS (opengl_versions); i++) {
      gint profileMask = 0;
      gint contextFlags = 0;

      if ((opengl_versions[i].major > 3
              || (opengl_versions[i].major == 3
                  && opengl_versions[i].minor >= 2))) {
        profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
        contextFlags |= GLX_CONTEXT_DEBUG_BIT_ARB;
      } else {
        break;
      }

      GST_DEBUG_OBJECT (context, "trying to create a GL %d.%d context",
          opengl_versions[i].major, opengl_versions[i].minor);

      context_glx->glx_context = _create_context_with_flags (context_glx,
          device, context_glx->priv->fbconfigs[0],
          (GLXContext) external_gl_context, opengl_versions[i].major,
          opengl_versions[i].minor, contextFlags, profileMask);

      if (context_glx->glx_context) {
        context_glx->priv->context_api = GST_GL_API_OPENGL3;
        break;
      }
    }
  }
  if (!context_glx->glx_context && gl_api & GST_GL_API_OPENGL) {
    context_glx->glx_context =
        glXCreateContext (device, window_x11->visual_info,
        (GLXContext) external_gl_context, TRUE);
    context_glx->priv->context_api = GST_GL_API_OPENGL;
  }

  if (context_glx->priv->fbconfigs)
    XFree (context_glx->priv->fbconfigs);

  if (!context_glx->glx_context) {
    g_set_error (error, GST_GL_CONTEXT_ERROR,
        GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "Failed to create opengl context");
    goto failure;
  }

  GST_LOG ("gl context id: %ld", (gulong) context_glx->glx_context);

  gst_object_unref (window);
  gst_object_unref (display);

  return TRUE;

failure:
  if (window)
    gst_object_unref (window);
  if (display)
    gst_object_unref (display);

  return FALSE;
}
Beispiel #25
0
gboolean
get_output_info_from_component (Component componentID)
{
  gboolean ret = FALSE;
  ComponentInstance instance;
  ImageSubCodecDecompressCapabilities caps;
  CodecInfo info;

  GST_LOG ("Creating an instance");

  /* 1. Create an instance */
  if (!(instance = OpenComponent (componentID))) {
    GST_WARNING ("Couldn't open component");
    return FALSE;
  }

  /* 2. initialize */
  memset (&caps, 0, sizeof (ImageSubCodecDecompressCapabilities));
  if (ImageCodecInitialize (instance, &caps) != noErr) {
    GST_WARNING ("ImageCodecInitialize() failed");
    goto beach;
  }
#if DEBUG_DUMP
  GST_LOG ("ImageSubCodecDecompressCapabilities");
  gst_util_dump_mem ((const guchar *) &caps,
      sizeof (ImageSubCodecDecompressCapabilities));
#endif

  GST_LOG ("recordSize:%ld", caps.recordSize);
  GST_LOG ("decompressRecordSize:%ld", caps.decompressRecordSize);
  GST_LOG ("canAsync:%d", caps.canAsync);

  /* 3. Get codec info */
  memset (&info, 0, sizeof (CodecInfo));
  if (ImageCodecGetCodecInfo (instance, &info) != noErr) {
    GST_WARNING ("ImageCodecInfo() failed");
    goto beach;
  };

#if DEBUG_DUMP
  GST_LOG ("CodecInfo");
  gst_util_dump_mem ((const guchar *) &info, sizeof (CodecInfo));
#endif

  GST_LOG ("version:%d", info.version);
  GST_LOG ("revisionLevel:%d", info.revisionLevel);
  GST_LOG ("vendor:%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (info.vendor));

  /* Compression flags */
  /* Contains flags (see below) that specify the decompression capabilities of
   * the component. Typically, these flags are of interest only to developers of
   * image decompressors. */
  GST_LOG ("decompressFlags:%lx", info.decompressFlags);
  if (info.decompressFlags & codecInfoDoes1)
    GST_LOG ("Depth 1 OK");
  if (info.decompressFlags & codecInfoDoes2)
    GST_LOG ("Depth 2 OK");
  if (info.decompressFlags & codecInfoDoes4)
    GST_LOG ("Depth 4 OK");
  if (info.decompressFlags & codecInfoDoes8)
    GST_LOG ("Depth 8 OK");
  if (info.decompressFlags & codecInfoDoes16)
    GST_LOG ("Depth 16 OK");
  if (info.decompressFlags & codecInfoDoes32)
    GST_LOG ("Depth 32 OK");
  GST_LOG ("compressFlags:%lx", info.compressFlags);

  /* Format FLAGS */
  /* Contains flags (see below) that describe the possible format for compressed
   * data produced by this component and the format of compressed files that the
   * component can handle during decompression. Typically, these flags are of
   * interest only to developers of compressor components.
   */
  GST_LOG ("formatFlags:%lx", info.formatFlags);
  if (info.formatFlags & codecInfoDepth1)
    GST_LOG ("Depth 1 OK");
  if (info.formatFlags & codecInfoDepth2)
    GST_LOG ("Depth 2 OK");
  if (info.formatFlags & codecInfoDepth4)
    GST_LOG ("Depth 4 OK");
  if (info.formatFlags & codecInfoDepth8)
    GST_LOG ("Depth 8 OK");
  if (info.formatFlags & codecInfoDepth16)
    GST_LOG ("Depth 16 OK");
  if (info.formatFlags & codecInfoDepth24)
    GST_LOG ("Depth 24 OK");
  if (info.formatFlags & codecInfoDepth32)
    GST_LOG ("Depth 32 OK");
  if (info.formatFlags & codecInfoDepth33)
    GST_LOG ("Depth 33 OK");
  if (info.formatFlags & codecInfoDepth34)
    GST_LOG ("Depth 34 OK");
  if (info.formatFlags & codecInfoDepth36)
    GST_LOG ("Depth 36 OK");
  if (info.formatFlags & codecInfoDepth40)
    GST_LOG ("Depth 40 OK");
  if (info.formatFlags & codecInfoStoresClut)
    GST_LOG ("StoresClut OK");
  if (info.formatFlags & codecInfoDoesLossless)
    GST_LOG ("Lossless OK");
  if (info.formatFlags & codecInfoSequenceSensitive)
    GST_LOG ("SequenceSentitive OK");


  GST_LOG ("compressionAccuracy:%u", info.compressionAccuracy);
  GST_LOG ("decompressionAccuracy:%u", info.decompressionAccuracy);
  GST_LOG ("compressionSpeed:%d", info.compressionSpeed);
  GST_LOG ("decompressionSpeed:%d", info.decompressionSpeed);
  GST_LOG ("compressionLevel:%u", info.compressionLevel);
  GST_LOG ("minimumHeight:%d", info.minimumHeight);
  GST_LOG ("minimumWidth:%d", info.minimumWidth);

/*   /\* . Call ImageCodecPreDecompress *\/ */
/*   memset(&params, 0, sizeof(CodecDecompressParams)); */
/*   GST_LOG ("calling imagecodecpredecompress"); */
/*   if (ImageCodecPreDecompress (instance, &params) != noErr) { */
/*     GST_WARNING ("Error in ImageCodecPreDecompress"); */
/*     goto beach; */
/*   } */

/*   GST_INFO ("sequenceID : %d", params.sequenceID); */

  ret = TRUE;

beach:
  /* Free instance */
  CloseComponent (instance);
  return TRUE;
}
static GstTagList *
ape_demux_parse_tags (const guint8 * data, gint size)
{
  GstTagList *taglist = gst_tag_list_new ();

  GST_LOG ("Reading tags from chunk of size %u bytes", size);

  /* get rid of header/footer */
  if (size >= 32 && memcmp (data, "APETAGEX", 8) == 0) {
    data += 32;
    size -= 32;
  }
  if (size > 32 && memcmp (data + size - 32, "APETAGEX", 8) == 0) {
    size -= 32;
  }

  /* read actual tags - at least 10 bytes for tag header */
  while (size >= 10) {
    guint len, n = 8;
    gchar *tag, *val;
    const gchar *gst_tag;
    GType gst_tag_type;

    /* find tag type and size */
    len = GST_READ_UINT32_LE (data);
    while (n < size && data[n] != 0x0)
      n++;
    if (n == size)
      break;
    g_assert (data[n] == 0x0);
    n++;
    if (size - n < len)
      break;

    /* If the tag is empty, skip to the next one */
    if (len == 0)
      goto next_tag;

    /* read */
    tag = g_strndup ((gchar *) data + 8, n - 9);
    val = g_strndup ((gchar *) data + n, len);

    GST_LOG ("tag [%s], val[%s]", tag, val);

    /* special-case 'media' tag, could be e.g. "CD 1/2" */
    if (g_ascii_strcasecmp (tag, "media") == 0) {
      gchar *sp, *sp2;

      g_free (tag);
      tag = g_strdup ("discnumber");
      /* get rid of the medium in front */
      sp = strchr (val, ' ');
      while (sp != NULL && (sp2 = strchr (sp + 1, ' ')) != NULL)
        sp = sp2;
      if (sp) {
        g_memmove (val, sp + 1, strlen (sp + 1) + 1);
      }
    }

    if (ape_demux_get_gst_tag_from_tag (tag, &gst_tag, &gst_tag_type)) {
      GValue v = { 0, };

      switch (gst_tag_type) {
        case G_TYPE_INT:{
          gint v_int;

          if (sscanf (val, "%d", &v_int) == 1) {
            g_value_init (&v, G_TYPE_INT);
            g_value_set_int (&v, v_int);
          }
          break;
        }
        case G_TYPE_UINT:{
          guint v_uint, count;

          if (strcmp (gst_tag, GST_TAG_TRACK_NUMBER) == 0) {
            gint dummy;

            if (sscanf (val, "%u", &v_uint) == 1 && v_uint > 0) {
              g_value_init (&v, G_TYPE_UINT);
              g_value_set_uint (&v, v_uint);
            }
            GST_LOG ("checking for track count: %s", val);
            /* might be 0/N or -1/N to specify that there is only a count */
            if (sscanf (val, "%d/%u", &dummy, &count) == 2 && count > 0) {
              gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
                  GST_TAG_TRACK_COUNT, count, NULL);
            }
          } else if (strcmp (gst_tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0) {
            gint dummy;

            if (sscanf (val, "%u", &v_uint) == 1 && v_uint > 0) {
              g_value_init (&v, G_TYPE_UINT);
              g_value_set_uint (&v, v_uint);
            }
            GST_LOG ("checking for volume count: %s", val);
            /* might be 0/N or -1/N to specify that there is only a count */
            if (sscanf (val, "%d/%u", &dummy, &count) == 2 && count > 0) {
              gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
                  GST_TAG_ALBUM_VOLUME_COUNT, count, NULL);
            }
          } else if (sscanf (val, "%u", &v_uint) == 1) {
            g_value_init (&v, G_TYPE_UINT);
            g_value_set_uint (&v, v_uint);
          }
          break;
        }
        case G_TYPE_STRING:{
          g_value_init (&v, G_TYPE_STRING);
          g_value_set_string (&v, val);
          break;
        }
        case G_TYPE_DOUBLE:{
          gdouble v_double;
          gchar *endptr;

          /* floating point strings can be "4,123" or "4.123" depending on
           * the locale. We need to be able to parse and read either version
           * no matter what our current locale is */
          g_strdelimit (val, ",", '.');
          v_double = g_ascii_strtod (val, &endptr);
          if (endptr != val) {
            g_value_init (&v, G_TYPE_DOUBLE);
            g_value_set_double (&v, v_double);
          }

          break;
        }
        default:{
          if (gst_tag_type == GST_TYPE_DATE) {
            gint v_int;

            if (sscanf (val, "%d", &v_int) == 1) {
              GDate *date = g_date_new_dmy (1, 1, v_int);

              g_value_init (&v, GST_TYPE_DATE);
              gst_value_set_date (&v, date);
              g_date_free (date);
            }
          } else {
            GST_WARNING ("Unhandled tag type '%s' for tag '%s'",
                g_type_name (gst_tag_type), gst_tag);
          }
          break;
        }
      }
      if (G_VALUE_TYPE (&v) != 0) {
        gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
            gst_tag, &v, NULL);
        g_value_unset (&v);
      }
    }
    GST_DEBUG ("Read tag %s: %s", tag, val);
    g_free (tag);
    g_free (val);

    /* move data pointer */
  next_tag:
    size -= len + n;
    data += len + n;
  }

  GST_DEBUG ("Taglist: %" GST_PTR_FORMAT, taglist);
  return taglist;
}
Beispiel #27
0
void
dump_codec_decompress_params (CodecDecompressParams * params)
{
  GST_LOG ("params %p", params);

#if DEBUG_DUMP
  gst_util_dump_mem ((const guchar *) params, sizeof (CodecDecompressParams));
#endif

  GST_LOG ("SequenceID:%ld", params->sequenceID);
  GST_LOG ("imageDescription:%p", params->imageDescription);
  GST_LOG ("data:%p", params->data);
  GST_LOG ("bufferSize:%ld", params->bufferSize);
  GST_LOG ("frameNumber:%ld", params->frameNumber);
  GST_LOG ("startLine:%ld  , StopLine:%ld", params->startLine,
      params->stopLine);
  GST_LOG ("conditionFlags:0x%lx", params->conditionFlags);
  GST_LOG ("callerFlags:0x%x", params->callerFlags);
  GST_LOG ("capabilities:%p", params->capabilities);
  GST_LOG ("port:%p", params->port);
  GST_LOG ("dstPixMap");
#if DEBUG_DUMP
  gst_util_dump_mem ((const guchar *) &params->dstPixMap, sizeof (PixMap));
#endif

  GST_LOG ("maskBits:%p", params->maskBits);
  GST_LOG ("mattePixMap:%p", params->mattePixMap);
  GST_LOG ("srcRect %d/%d/%d/%d",
      params->srcRect.top, params->srcRect.bottom,
      params->srcRect.left, params->srcRect.right);

  GST_LOG ("matrix:%p", params->matrix);
  GST_LOG ("accuracy:%ld", params->accuracy);
  GST_LOG ("transferMode:%d", params->transferMode);
  GST_LOG ("frameTime:%p", params->frameTime);
  GST_LOG ("matrixFlags:%x", params->matrixFlags);

  GST_LOG ("dstRect %d/%d/%d/%d",
      params->dstRect.top, params->dstRect.bottom,
      params->dstRect.left, params->dstRect.right);

  GST_LOG ("sourceData:%p", params->sourceData);

  if (params->wantedDestinationPixelTypes) {
    OSType *tmp;

    for (tmp = *params->wantedDestinationPixelTypes; *tmp; tmp++)
      GST_LOG ("Destination pixel %" GST_FOURCC_FORMAT, QT_FOURCC_ARGS (*tmp));
  }
}
/**
 * gst_missing_plugin_message_get_installer_detail:
 * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT
 *
 * Returns an opaque string containing all the details about the missing
 * element to be passed to an external installer called via
 * gst_install_plugins_async() or gst_install_plugins_sync().
 * 
 * This function is mainly for applications that call external plugin
 * installation mechanisms using one of the two above-mentioned functions.
 *
 * Returns: a newly-allocated detail string, or NULL on error. Free string
 *          with g_free() when not needed any longer.
 */
gchar *
gst_missing_plugin_message_get_installer_detail (GstMessage * msg)
{
  GstMissingType missing_type;
  const gchar *progname;
  const gchar *type;
  GString *str = NULL;
  gchar *detail = NULL;
  gchar *desc;

  g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL);

  GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure);

  missing_type = missing_structure_get_type (msg->structure);
  if (missing_type == GST_MISSING_TYPE_UNKNOWN) {
    GST_WARNING ("couldn't parse 'type' field");
    goto error;
  }

  type = gst_structure_get_string (msg->structure, "type");
  g_assert (type != NULL);      /* validity already checked above */

  /* FIXME: use gst_installer_detail_new() here too */
  str = g_string_new (GST_DETAIL_STRING_MARKER "|");
  g_string_append_printf (str, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR);

  progname = (const gchar *) g_get_prgname ();
  if (progname) {
    g_string_append_printf (str, "%s|", progname);
  } else {
    g_string_append_printf (str, "pid/%lu|", (gulong) getpid ());
  }

  desc = gst_missing_plugin_message_get_description (msg);
  if (desc) {
    g_strdelimit (desc, "|", '#');
    g_string_append_printf (str, "%s|", desc);
    g_free (desc);
  } else {
    g_string_append (str, "|");
  }

  switch (missing_type) {
    case GST_MISSING_TYPE_URISOURCE:
    case GST_MISSING_TYPE_URISINK:
    case GST_MISSING_TYPE_ELEMENT:
      if (!missing_structure_get_string_detail (msg->structure, &detail))
        goto error;
      break;
    case GST_MISSING_TYPE_DECODER:
    case GST_MISSING_TYPE_ENCODER:{
      GstCaps *caps = NULL;

      if (!missing_structure_get_caps_detail (msg->structure, &caps))
        goto error;

      detail = gst_caps_to_string (caps);
      gst_caps_unref (caps);
      break;
    }
    default:
      g_return_val_if_reached (NULL);
  }

  g_string_append_printf (str, "%s-%s", type, detail);
  g_free (detail);

  return g_string_free (str, FALSE);

/* ERRORS */
error:
  {
    GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg);
    if (str)
      g_string_free (str, TRUE);
    return NULL;
  }
}
Beispiel #29
0
static void
gst_dtsdec_class_init (GstDtsDecClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
  GstAudioDecoderClass *gstbase_class;
  guint cpuflags;

  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
  gstbase_class = (GstAudioDecoderClass *) klass;

  gobject_class->set_property = gst_dtsdec_set_property;
  gobject_class->get_property = gst_dtsdec_get_property;

  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&sink_factory));
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&src_factory));
  gst_element_class_set_details_simple (gstelement_class, "DTS audio decoder",
      "Codec/Decoder/Audio",
      "Decodes DTS audio streams",
      "Jan Schmidt <*****@*****.**>, "
      "Ronald Bultje <*****@*****.**>");

  gstbase_class->start = GST_DEBUG_FUNCPTR (gst_dtsdec_start);
  gstbase_class->stop = GST_DEBUG_FUNCPTR (gst_dtsdec_stop);
  gstbase_class->set_format = GST_DEBUG_FUNCPTR (gst_dtsdec_set_format);
  gstbase_class->parse = GST_DEBUG_FUNCPTR (gst_dtsdec_parse);
  gstbase_class->handle_frame = GST_DEBUG_FUNCPTR (gst_dtsdec_handle_frame);

  /**
   * GstDtsDec::drc
   *
   * Set to true to apply the recommended DTS dynamic range compression
   * to the audio stream. Dynamic range compression makes loud sounds
   * softer and soft sounds louder, so you can more easily listen
   * to the stream without disturbing other people.
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DRC,
      g_param_spec_boolean ("drc", "Dynamic Range Compression",
          "Use Dynamic Range Compression", FALSE,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  klass->dts_cpuflags = 0;

#if HAVE_ORC
  cpuflags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
  if (cpuflags & ORC_TARGET_MMX_MMX)
    klass->dts_cpuflags |= MM_ACCEL_X86_MMX;
  if (cpuflags & ORC_TARGET_MMX_3DNOW)
    klass->dts_cpuflags |= MM_ACCEL_X86_3DNOW;
  if (cpuflags & ORC_TARGET_MMX_MMXEXT)
    klass->dts_cpuflags |= MM_ACCEL_X86_MMXEXT;
#else
  cpuflags = 0;
  klass->dts_cpuflags = 0;
#endif

  GST_LOG ("CPU flags: dts=%08x, liboil=%08x", klass->dts_cpuflags, cpuflags);
}
static GstTagList *
read_tags_from_file (const gchar * file, gboolean push_mode)
{
  GstStateChangeReturn state_ret;
  GstTagList *tags = NULL;
  GstMessage *msg;
  GstElement *src, *sep, *sink, *id3demux, *pipeline;
  GstBus *bus;
  gchar *path;

  pipeline = gst_pipeline_new ("pipeline");
  fail_unless (pipeline != NULL, "Failed to create pipeline!");

  bus = gst_element_get_bus (pipeline);

  /* kids, don't use a sync handler for this at home, really; we do because
   * we just want to abort and nothing else */
  gst_bus_set_sync_handler (bus, error_cb, (gpointer) file, NULL);

  src = gst_element_factory_make ("filesrc", "filesrc");
  fail_unless (src != NULL, "Failed to create 'filesrc' element!");

  if (push_mode) {
    sep = gst_element_factory_make ("queue", "queue");
    fail_unless (sep != NULL, "Failed to create 'queue' element");
  } else {
    sep = gst_element_factory_make ("identity", "identity");
    fail_unless (sep != NULL, "Failed to create 'identity' element");
  }

  id3demux = gst_element_factory_make ("id3demux", "id3demux");
  fail_unless (id3demux != NULL, "Failed to create 'id3demux' element!");

  sink = gst_element_factory_make ("fakesink", "fakesink");
  fail_unless (sink != NULL, "Failed to create 'fakesink' element!");

  gst_bin_add_many (GST_BIN (pipeline), src, sep, id3demux, sink, NULL);

  fail_unless (gst_element_link (src, sep));
  fail_unless (gst_element_link (sep, id3demux));
  fail_unless (gst_element_link (id3demux, sink));

  path = g_build_filename (GST_TEST_FILES_PATH, file, NULL);
  GST_LOG ("reading file '%s'", path);
  g_object_set (src, "location", path, NULL);

  state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
  fail_unless (state_ret != GST_STATE_CHANGE_FAILURE);

  if (state_ret == GST_STATE_CHANGE_ASYNC) {
    GST_LOG ("waiting for pipeline to reach PAUSED state");
    state_ret = gst_element_get_state (pipeline, NULL, NULL, -1);
    fail_unless_equals_int (state_ret, GST_STATE_CHANGE_SUCCESS);
  }

  GST_LOG ("PAUSED, let's retrieve our tags");

  msg = gst_bus_poll (bus, GST_MESSAGE_TAG, -1);
  fail_unless (msg != NULL, "Expected TAG message on bus! (%s)", file);

  gst_message_parse_tag (msg, &tags);
  fail_unless (tags != NULL, "TAG message did not contain taglist! (%s)", file);

  gst_message_unref (msg);
  gst_object_unref (bus);

  fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
      GST_STATE_CHANGE_SUCCESS);
  gst_object_unref (pipeline);

  g_free (path);

  GST_INFO ("%s: tags = %" GST_PTR_FORMAT, file, tags);
  return tags;
}