Esempio n. 1
0
static gboolean rc_plugin_tag_flac_change(const gchar *src_path,
    const gchar *target_path, const GstTagList *tag_list)
{
    GstElement *tag_filesrc = NULL;
    GstElement *tag_filesink = NULL;
    GstElement *tagger = NULL;
    GstBus *bus = NULL;
    if(src_path==NULL) return FALSE;
    if(target_path==NULL) return FALSE;
    if(tag_list==NULL) return FALSE;
    if(g_access(src_path, W_OK)!=0) return FALSE;
    tagger = gst_element_factory_make("flactag", "flac-tagger");
    if(tagger==NULL) goto error_out;
    tag_filesrc = gst_element_factory_make("filesrc", "tag-filesrc");
    if(tag_filesrc==NULL) goto error_out;
    tag_filesink = gst_element_factory_make("filesink", "tag-filesink");
    if(tag_filesink==NULL) goto error_out;
    g_object_set(G_OBJECT(tag_filesrc), "location", src_path, NULL);
    g_object_set(G_OBJECT(tag_filesink), "location", target_path, NULL);
    tagger_pipeline = gst_pipeline_new("tagger-pipeline");
    gst_tag_setter_merge_tags(GST_TAG_SETTER(tagger), tag_list,
        GST_TAG_MERGE_REPLACE);
    gst_bin_add_many(GST_BIN(tagger_pipeline), tag_filesrc, tagger,
        tag_filesink, NULL);
    if(!gst_element_link_many(tag_filesrc, tagger, tag_filesink, NULL))
        goto error_out;
    bus = gst_pipeline_get_bus(GST_PIPELINE(tagger_pipeline));
    gst_bus_add_watch(bus, (GstBusFunc)rc_plugin_tag_writer_bus_cb, NULL);
    gst_object_unref(bus);
    gst_element_set_state(tagger_pipeline, GST_STATE_NULL);
    gst_element_set_state(tagger_pipeline, GST_STATE_READY);
    if(gst_element_set_state(tagger_pipeline, GST_STATE_PLAYING)
        ==GST_STATE_CHANGE_FAILURE)
        goto error_out;
    return TRUE;
    error_out:
        if(tagger!=NULL) gst_object_unref(tagger);
        if(tag_filesrc!=NULL) gst_object_unref(tag_filesrc);
        if(tag_filesink!=NULL) gst_object_unref(tag_filesink);
        if(tagger_pipeline!=NULL) gst_object_unref(tagger_pipeline);
        tagger_pipeline = NULL;
        return FALSE;
}
Esempio n. 2
0
static gboolean
gst_vorbis_enc_stop (GstAudioEncoder * enc)
{
  GstVorbisEnc *vorbisenc = GST_VORBISENC (enc);

  GST_DEBUG_OBJECT (enc, "stop");
  vorbis_block_clear (&vorbisenc->vb);
  vorbis_dsp_clear (&vorbisenc->vd);
  vorbis_info_clear (&vorbisenc->vi);
  g_free (vorbisenc->last_message);
  vorbisenc->last_message = NULL;
  gst_tag_list_free (vorbisenc->tags);
  vorbisenc->tags = NULL;
  g_slist_foreach (vorbisenc->headers, (GFunc) gst_buffer_unref, NULL);
  vorbisenc->headers = NULL;

  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));

  return TRUE;
}
Esempio n. 3
0
static gboolean
gst_vp8_enc_sink_event (GstPad * pad, GstEvent * event)
{
  GstVP8Enc *enc = GST_VP8_ENC (gst_pad_get_parent (pad));
  gboolean ret;

  if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) {
    GstTagList *list;
    GstTagSetter *setter = GST_TAG_SETTER (enc);
    const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);

    gst_event_parse_tag (event, &list);
    gst_tag_setter_merge_tags (setter, list, mode);
  }

  ret = enc->base_sink_event_func (pad, event);
  gst_object_unref (enc);

  return ret;
}
static gboolean
gst_speex_enc_stop (GstAudioEncoder * benc)
{
  GstSpeexEnc *enc = GST_SPEEX_ENC (benc);

  GST_DEBUG_OBJECT (enc, "stop");
  enc->header_sent = FALSE;
  if (enc->state) {
    speex_encoder_destroy (enc->state);
    enc->state = NULL;
  }
  speex_bits_destroy (&enc->bits);
  speex_bits_set_bit_buffer (&enc->bits, NULL, 0);
  gst_tag_list_unref (enc->tags);
  enc->tags = NULL;

  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));

  return TRUE;
}
Esempio n. 5
0
static gboolean
gst_opus_enc_stop (GstAudioEncoder * benc)
{
  GstOpusEnc *enc = GST_OPUS_ENC (benc);

  GST_DEBUG_OBJECT (enc, "stop");
  enc->header_sent = FALSE;
  if (enc->state) {
    opus_multistream_encoder_destroy (enc->state);
    enc->state = NULL;
  }
  gst_tag_list_free (enc->tags);
  enc->tags = NULL;
  g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
  g_slist_free (enc->headers);
  enc->headers = NULL;
  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));

  return TRUE;
}
Esempio n. 6
0
static GstStateChangeReturn
gst_ffmpegmux_change_state (GstElement * element, GstStateChange transition)
{
  GstFlowReturn ret;
  GstFFMpegMux *ffmpegmux = (GstFFMpegMux *) (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      gst_collect_pads_start (ffmpegmux->collect);
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_collect_pads_stop (ffmpegmux->collect);
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_tag_setter_reset_tags (GST_TAG_SETTER (ffmpegmux));
      if (ffmpegmux->opened) {
        ffmpegmux->opened = FALSE;
        url_fclose (ffmpegmux->context->pb);
      }
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
Esempio n. 7
0
static gboolean
gst_celt_enc_stop (GstAudioEncoder * benc)
{
  GstCeltEnc *enc = GST_CELT_ENC (benc);

  GST_DEBUG_OBJECT (enc, "stop");
  enc->header_sent = FALSE;
  if (enc->state) {
    celt_encoder_destroy (enc->state);
    enc->state = NULL;
  }
  if (enc->mode) {
    celt_mode_destroy (enc->mode);
    enc->mode = NULL;
  }
  memset (&enc->header, 0, sizeof (enc->header));

  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));

  return TRUE;
}
GST_END_TEST
GST_START_TEST (test_merge_modes_skip_empty)
{
  GstTagMergeMode mode;

  for (mode = GST_TAG_MERGE_REPLACE_ALL; mode < GST_TAG_MERGE_COUNT; mode++) {
    gint i;

    for (i = 0; i < 2; i++) {
      GstElement *enc;
      GstTagSetter *setter;
      GstTagList *list1, *list2, *merged;

      enc = g_object_new (GST_TYPE_DUMMY_ENC, NULL);
      fail_unless (enc != NULL);

      setter = GST_TAG_SETTER (enc);
      list1 = gst_tag_list_new_empty ();
      list2 = gst_tag_list_new_empty ();

      if (i == 1) {
        gst_tag_list_add (list2, GST_TAG_MERGE_APPEND, GST_TAG_ARTIST,
            "artist2", NULL);
      }

      gst_tag_setter_merge_tags (setter, list2, mode);

      merged = gst_tag_list_merge (list1, list2, mode);

      fail_unless_equals_int (tag_list_length (gst_tag_setter_get_tag_list
              (setter)), tag_list_length (merged));

      gst_tag_list_unref (list1);
      gst_tag_list_unref (list2);
      gst_tag_list_unref (merged);
      gst_object_unref (enc);
    }
  }
}
Esempio n. 9
0
static GstFlowReturn
gst_opus_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
{
  GstOpusEnc *enc;
  GstFlowReturn ret = GST_FLOW_OK;

  enc = GST_OPUS_ENC (benc);
  GST_DEBUG_OBJECT (enc, "handle_frame");

  if (!enc->header_sent) {
    GstCaps *caps;

    g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
    g_slist_free (enc->headers);
    enc->headers = NULL;

    gst_opus_header_create_caps (&caps, &enc->headers, enc->n_channels,
        enc->n_stereo_streams, enc->sample_rate, enc->channel_mapping_family,
        enc->decoding_channel_mapping,
        gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)));


    /* negotiate with these caps */
    GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);

    gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
    gst_caps_unref (caps);

    enc->header_sent = TRUE;
  }

  GST_DEBUG_OBJECT (enc, "received buffer %p of %u bytes", buf,
      buf ? GST_BUFFER_SIZE (buf) : 0);

  ret = gst_opus_enc_encode (enc, buf);

  return ret;
}
Esempio n. 10
0
static gboolean
gst_jif_mux_sink_event (GstPad * pad, GstEvent * event)
{
    GstJifMux *self = GST_JIF_MUX (GST_PAD_PARENT (pad));
    gboolean ret;

    switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_TAG: {
        GstTagList *list;
        GstTagSetter *setter = GST_TAG_SETTER (self);
        const GstTagMergeMode mode = gst_tag_setter_get_tag_merge_mode (setter);

        gst_event_parse_tag (event, &list);

        gst_tag_setter_merge_tags (setter, list, mode);
        break;
    }
    default:
        break;
    }
    ret = gst_pad_event_default (pad, event);
    return ret;
}
Esempio n. 11
0
static gboolean
gst_speex_enc_sinkevent (GstPad * pad, GstEvent * event)
{
  gboolean res = TRUE;
  GstSpeexEnc *enc;

  enc = GST_SPEEX_ENC (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
      if (enc->setup)
        gst_speex_enc_encode (enc, TRUE);
      res = gst_pad_event_default (pad, event);
      break;
    case GST_EVENT_TAG:
    {
      if (enc->tags) {
        GstTagList *list;

        gst_event_parse_tag (event, &list);
        gst_tag_list_insert (enc->tags, list,
            gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
      } else {
        g_assert_not_reached ();
      }
      res = gst_pad_event_default (pad, event);
      break;
    }
    default:
      res = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (enc);

  return res;
}
static gpointer
test_threads_thread_func3 (gpointer data)
{
  GstTagSetter *setter = GST_TAG_SETTER (data);
  GTimer *timer;

  timer = g_timer_new ();

  g_atomic_int_inc (&threads_running);
  while (g_atomic_int_get (&spin_and_wait))
    g_usleep (0);

  GST_INFO ("Go!");
  g_timer_start (timer);

  while (g_timer_elapsed (timer, NULL) < THREADS_TEST_SECONDS) {
    gst_tag_setter_reset_tags (setter);
  }

  g_timer_destroy (timer);
  GST_INFO ("Done");

  return NULL;
}
Esempio n. 13
0
static GstTagList *
gst_tag_mux_get_tags (GstTagMux * mux)
{
  GstTagSetter *tagsetter = GST_TAG_SETTER (mux);
  const GstTagList *tagsetter_tags;
  GstTagMergeMode merge_mode;

  if (mux->priv->final_tags)
    return mux->priv->final_tags;

  tagsetter_tags = gst_tag_setter_get_tag_list (tagsetter);
  merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter);

  GST_LOG_OBJECT (mux, "merging tags, merge mode = %d", merge_mode);
  GST_LOG_OBJECT (mux, "event tags: %" GST_PTR_FORMAT, mux->priv->event_tags);
  GST_LOG_OBJECT (mux, "set   tags: %" GST_PTR_FORMAT, tagsetter_tags);

  mux->priv->final_tags =
      gst_tag_list_merge (tagsetter_tags, mux->priv->event_tags, merge_mode);

  GST_LOG_OBJECT (mux, "final tags: %" GST_PTR_FORMAT, mux->priv->final_tags);

  return mux->priv->final_tags;
}
Esempio n. 14
0
void TransCoder::pipeRun(int ind)
{
    GstElement *source, *dec, *conv, *encoder, *muxer, *fileout, *tagger, *volume;
    GstBus *bus;
    GstState state;
    GstPad *audiopad;//, *encoderpad;

    numTrack = ind;
    bool preenc;
    int vbr = 0;

    loop = g_main_loop_new (NULL, FALSE);

    pipeline = gst_pipeline_new ("audio-transcoder");

    // Входной файл
    source   = gst_element_factory_make ("filesrc", "file-source");
    g_object_set (source, "location", localFileNamesEncoder->fromUnicode(refparser->getSoundFile()).data(), NULL);

    dec = gst_element_factory_make ("decodebin", "decoder");
    g_signal_connect (dec, "new-decoded-pad", G_CALLBACK (cb_newpad), NULL);
    gst_bin_add_many (GST_BIN (pipeline), source, dec, NULL);
    gst_element_link (source, dec);

    audio = gst_bin_new ("audiobin");
    conv = gst_element_factory_make ("audioconvert", "aconv");
    volume = gst_element_factory_make ("volume", "vol");
    audiopad = gst_element_get_static_pad (conv, "sink");
    fileout = gst_element_factory_make ("filesink", "file-out");

    // Выходной файл
    QRegExp rxFileSlash("/");
    QRegExp rxTilda("^~(.*)");
    QString filename;
    QTextStream out(stdout);
    QString comment = trUtf8("CuePlayer ") + qApp->applicationVersion();
    QString trackName = refparser->getTrackTitle(ind);
    QString title = refparser->getTitle();
    trackName.replace(rxFileSlash, trUtf8("⁄"));
    title.replace(rxFileSlash, trUtf8("⁄"));
    if (rxTilda.indexIn(lineEdit->text()) != -1)
        lineEdit->setText(QDir::homePath() + rxTilda.cap(1));
    QDir updir(lineEdit->text());
    if (!updir.exists())
        updir.mkdir(lineEdit->text());
    QString dirname = lineEdit->text() + "/" + title;
    QDir dir(dirname);
    if (!dir.exists())
        dir.mkdir(dirname);
    if (ind < 10)
        filename = dirname + "/" + "0" + QString::number(ind,10) + " - " + trackName + "." + containerBox->currentText();
    else
        filename = dirname + "/" + QString::number(ind,10) + " - " + trackName + "." + containerBox->currentText();
    g_object_set (fileout, "location", localFileNamesEncoder->fromUnicode(filename).data(), NULL);

    tmpfile.setFileName(dirname + "/" + QString::number(ind,10) + " - " + trackName + ".tmp");

    switch (codecBox->currentIndex())
    {
    case CODEC_VORBIS:
        if (tmpfile.exists())
        {
            g_object_set (source, "location", localFileNamesEncoder->fromUnicode(tmpfile.fileName()).data(), NULL);
            encoder = gst_element_factory_make ("vorbisenc", "audio-encoder");
            tagger = gst_element_factory_make ("vorbistag", "tagger");
            muxer = gst_element_factory_make ("oggmux", "audio-muxer");
            gst_bin_add_many (GST_BIN (audio), conv, encoder, tagger, muxer, fileout, NULL);
            gst_element_link_many (conv, encoder, tagger, muxer, fileout, NULL);
            if (!settings.value("preferences/vorbisquality").isNull())
            {
                g_object_set (encoder,
                              "max-bitrate", settings.value("preferences/vorbismaxbitrate").toInt(),
                              "bitrate", settings.value("preferences/vorbisbitrate").toInt(),
                              "min-bitrate", settings.value("preferences/vorbisminbitrate").toInt(),
                              "quality", settings.value("preferences/vorbisquality").toDouble()/10,
                              "managed", settings.value("preferences/vorbismanaged").toBool(),
                              NULL);
            }
            gst_tag_setter_add_tags (GST_TAG_SETTER (tagger),
                                     GST_TAG_MERGE_REPLACE_ALL,
                                     GST_TAG_TITLE, refparser->getTrackTitle(ind).toUtf8().data(),
                                     GST_TAG_ARTIST, refparser->getPerformer().toUtf8().data(),
                                     GST_TAG_TRACK_NUMBER, ind,
                                     GST_TAG_TRACK_COUNT, refparser->getTrackNumber(),
                                     GST_TAG_ALBUM, refparser->getAlbum().toUtf8().data(),
                                     GST_TAG_ENCODER, APPNAME,
                                     GST_TAG_ENCODER_VERSION, qApp->applicationVersion().toUtf8().data(),
                                     GST_TAG_COMMENT, comment.toUtf8().data(),
                                     GST_TAG_CODEC, "vorbis",
                                     NULL);
            containerBox->setCurrentIndex(CODEC_VORBIS);
        }
        else
        {
            preenc = true;
            encoder = gst_element_factory_make ("flacenc", "audio-encoder");
            g_object_set(encoder, "quality", 0, NULL);
            gst_bin_add_many (GST_BIN (audio), conv, volume, encoder, fileout, NULL);
            gst_element_link_many (conv, volume, encoder, fileout, NULL);
            g_object_set (volume, "mute", true, NULL);
            g_object_set (fileout, "location", localFileNamesEncoder->fromUnicode(tmpfile.fileName()).data(), NULL);
        }
        break;
    case CODEC_LAME:
        encoder = gst_element_factory_make ("lame", "audio-encoder");
        muxer = gst_element_factory_make ("id3v2mux", "audio-muxer");
        gst_bin_add_many (GST_BIN (audio), conv, encoder, muxer, fileout, NULL);
        gst_element_link_many (conv, encoder, muxer, fileout, NULL);

        if (settings.value("preferences/lamevbr").toInt())
            vbr = settings.value("preferences/lamevbr").toInt() + 1;

        if (!settings.value("preferences/lamequality").isNull())
        {
            g_object_set (encoder,
                          "bitrate", bitrateList.at(settings.value("preferences/lamebitrate").toInt()),
                          //"compression-ratio", settings.value("preferences/lamecompressionratio").toInt(), // Баг. Перекрывает VBR
                          "quality", settings.value("preferences/lamequality").toInt(),
                          "mode", settings.value("preferences/lamemode").toInt(),
                          "force-ms", settings.value("preferences/lameforcems").toBool(),
                          "free-format", settings.value("preferences/lamefreeformat").toBool(),
                          "copyright", settings.value("preferences/lamecopyright").toBool(),
                          "original", settings.value("preferences/lameoriginal").toBool(),
                          "error-protection", settings.value("preferences/lameerrprot").toBool(),
                          "padding-type", settings.value("preferences/lamepaddingtype").toInt(),
                          "extension", settings.value("preferences/lameextension").toBool(),
                          "strict-iso", settings.value("preferences/lamestrictiso").toBool(),
                          "vbr", vbr,
                          "disable-reservoir", settings.value("preferences/lamedisrese").toBool(),
                          NULL);
        }
        gst_tag_setter_add_tags (GST_TAG_SETTER (muxer),
                                 GST_TAG_MERGE_REPLACE_ALL,
                                 GST_TAG_TITLE, refparser->getTrackTitle(ind).toUtf8().data(),
                                 GST_TAG_ARTIST, refparser->getPerformer().toUtf8().data(),
                                 GST_TAG_TRACK_NUMBER, ind,
                                 GST_TAG_TRACK_COUNT, refparser->getTrackNumber(),
                                 GST_TAG_ALBUM, refparser->getAlbum().toUtf8().data(),
                                 GST_TAG_ENCODER, APPNAME,
                                 GST_TAG_ENCODER_VERSION, qApp->applicationVersion().toUtf8().data(),
                                 GST_TAG_COMMENT, comment.toUtf8().data(),
                                 GST_TAG_CODEC, "lame",
                                 NULL);
        containerBox->setCurrentIndex(CODEC_LAME);
        break;
    case CODEC_FLAC:
        encoder = gst_element_factory_make ("flacenc", "audio-encoder");
        tagger = gst_element_factory_make ("flactag", "tagger");
        if (!settings.value("preferences/flacquality").isNull())
        {
            g_object_set (encoder,
                          "quality", settings.value("preferences/flacquality").toInt(),
                          "streamable-subset", settings.value("preferences/flacstreamablesubset").toBool(),
                          "mid-side-stereo", settings.value("preferences/flacmidsidestereo").toBool(),
                          "loose-mid-side-stereo", settings.value("preferences/flacloosemidsidestereo").toBool(),
                          "blocksize", settings.value("preferences/flacblocksize").toInt(),
                          "max-lpc-order", settings.value("preferences/flacmaxlpcorder").toInt(),
                          "qlp-coeff-precision", settings.value("preferences/flacqlpcoeffprecision").toInt(),
                          "qlp-coeff-prec-search", settings.value("preferences/flacqlpcoeffprecsearch").toBool(),
                          "escape-coding", settings.value("preferences/flacescapecoding").toBool(),
                          "exhaustive-model-search", settings.value("preferences/flacexhaustivemodelsearch").toBool(),
                          "min-residual-partition-order", settings.value("preferences/flacminresidualpartitionorder").toInt(),
                          "max-residual-partition-order", settings.value("preferences/flacmaxresidualpartitionorder").toInt(),
                          "rice-parameter-search-dist", settings.value("preferences/flacriceparametersearchdist").toInt(),
                          NULL);
        }
        gst_bin_add_many (GST_BIN (audio), conv, encoder, tagger, fileout, NULL);
        gst_element_link_many (conv, encoder, tagger, fileout, NULL);
        gst_tag_setter_add_tags (GST_TAG_SETTER (tagger),
                                 GST_TAG_MERGE_REPLACE_ALL,
                                 GST_TAG_TITLE, refparser->getTrackTitle(ind).toUtf8().data(),
                                 GST_TAG_ARTIST, refparser->getPerformer().toUtf8().data(),
                                 GST_TAG_TRACK_NUMBER, ind,
                                 GST_TAG_TRACK_COUNT, refparser->getTrackNumber(),
                                 GST_TAG_ALBUM, refparser->getAlbum().toUtf8().data(),
                                 GST_TAG_ENCODER, APPNAME,
                                 GST_TAG_ENCODER_VERSION, qApp->applicationVersion().toUtf8().data(),
                                 GST_TAG_COMMENT, comment.toUtf8().data(),
                                 GST_TAG_CODEC, "flac",
                                 NULL);
        containerBox->setCurrentIndex(CODEC_FLAC);
        break;
    case CODEC_FAAC:
        encoder = gst_element_factory_make ("faac", "audio-encoder");
        gst_bin_add_many (GST_BIN (audio), conv, encoder, fileout, NULL);
        gst_element_link_many (conv, encoder, fileout, NULL);
        if (!settings.value("preferences/faacprofile").isNull())
        {
            g_object_set(encoder,
                         "outputformat", settings.value("preferences/faacoutputformat").toInt(),
                         "bitrate", settings.value("preferences/faacbitrate").toInt(),
                         "profile", settings.value("preferences/faacprofile").toInt()+1,
                         "tns", settings.value("preferences/faactns").toBool(),
                         "midside", settings.value("preferences/faacmidside").toBool(),
                         "shortctl", settings.value("preferences/faacshortctl").toInt(),
                         NULL);
        }
        containerBox->setCurrentIndex(CODEC_FAAC);
        break;
    case CODEC_NO:
    default:
        break;
    }

    gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad));
    gst_object_unref (audiopad);
    gst_bin_add (GST_BIN (pipeline), audio);

    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
    gst_bus_add_watch (bus, bus_call, loop);
    gst_object_unref (bus);

    //g_signal_connect (pipeline, "deep-notify", G_CALLBACK (gst_object_default_deep_notify), NULL); // Дебаг!
    out << trUtf8("Кодируется: ") << refparser->getSoundFile() << endl;

    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    gst_element_get_state( GST_ELEMENT(pipeline), &state, NULL, GST_MSECOND * 300);
    if (state == GST_STATE_PLAYING)
    {
        timer->start(TIME);
        if (ind == refparser->getTrackNumber())
            setTrackTime(refparser->getTrackIndex(ind),saveTotalTime);
        else
            setTrackTime(refparser->getTrackIndex(ind),refparser->getTrackIndex(ind+1));
        if (preenc)
            g_object_set (volume, "mute", false, NULL);
        g_print ("Запущено...\n");
        g_main_loop_run (loop);
    }
    else
    {
        out << trUtf8("Ошибка перехода в PLAYING\n");
        transcode = false;
        stopAll();
    }
}
Esempio n. 15
0
int
main (int argc, char *argv[])
{
  GstElement *bin, *filesrc, *decoder, *encoder, *filesink;
  gchar *artist, *title, *ext, *filename;

  /* initialize GStreamer */
  gst_init (&argc, &argv);

  /* check that the argument is there */
  if (argc != 2) {
    g_print ("usage: %s <mp3 file>\n", argv[0]);
    return 1;
  }

  /* parse the mp3 name */
  artist = strrchr (argv[1], '/');
  if (artist == NULL)
    artist = argv[1];
  artist = g_strdup (artist);
  ext = strrchr (artist, '.');
  if (ext)
    *ext = '\0';
  title = strstr (artist, " - ");
  if (title == NULL) {
    g_print ("The format of the mp3 file is invalid.\n");
    g_print ("It needs to be in the form of artist - title.mp3.\n");
    return 1;
  }
  *title = '\0';
  title += 3;


  /* create a new bin to hold the elements */
  bin = gst_pipeline_new ("pipeline");
  g_assert (bin);

  /* create a file reader */
  filesrc = gst_element_factory_make ("filesrc", "disk_source");
  g_assert (filesrc);

  /* now it's time to get the decoder */
  decoder = gst_element_factory_make ("mad", "decode");
  if (!decoder) {
    g_print ("could not find plugin \"mad\"");
    return 1;
  }

  /* create the encoder */
  encoder = gst_element_factory_make ("vorbisenc", "encoder");
  if (!encoder) {
    g_print ("cound not find plugin \"vorbisenc\"");
    return 1;
  }

  /* and a file writer */
  filesink = gst_element_factory_make ("filesink", "filesink");
  g_assert (filesink);

  /* set the filenames */
  filename = g_strdup_printf ("%s.ogg", argv[1]);       /* easy solution */
  g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
  g_object_set (G_OBJECT (filesink), "location", filename, NULL);
  g_free (filename);

  /* make sure the tag setter uses our stuff
     (though that should already be default) */
  gst_tag_setter_set_merge_mode (GST_TAG_SETTER (encoder), GST_TAG_MERGE_KEEP);
  /* set the tagging information */
  gst_tag_setter_add (GST_TAG_SETTER (encoder), GST_TAG_MERGE_REPLACE,
      GST_TAG_ARTIST, artist, GST_TAG_TITLE, title, NULL);

  /* add objects to the main pipeline */
  gst_bin_add_many (GST_BIN (bin), filesrc, decoder, encoder, filesink, NULL);

  /* link the elements */
  gst_element_link_many (filesrc, decoder, encoder, filesink, NULL);

  /* start playing */
  gst_element_set_state (bin, GST_STATE_PLAYING);

  while (gst_bin_iterate (GST_BIN (bin)));

  /* stop the bin */
  gst_element_set_state (bin, GST_STATE_NULL);

  return 0;
}
static gboolean
gst_vp8_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
    GstVideoState * state)
{
  GstVP8Enc *encoder;
  vpx_codec_enc_cfg_t cfg;
  vpx_codec_err_t status;
  vpx_image_t *image;
  guint8 *data = NULL;
  GstCaps *caps;
  gboolean ret;

  encoder = GST_VP8_ENC (base_video_encoder);
  GST_DEBUG_OBJECT (base_video_encoder, "set_format");

  if (encoder->inited) {
    GST_DEBUG_OBJECT (base_video_encoder, "refusing renegotiation");
    return FALSE;
  }

  status = vpx_codec_enc_config_default (&vpx_codec_vp8_cx_algo, &cfg, 0);
  if (status != VPX_CODEC_OK) {
    GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
        ("Failed to get default encoder configuration"), ("%s",
            gst_vpx_error_name (status)));
    return FALSE;
  }

  /* Scale default bitrate to our size */
  cfg.rc_target_bitrate = gst_util_uint64_scale (cfg.rc_target_bitrate,
      state->width * state->height,
      cfg.g_w * cfg.g_h);

  cfg.g_w = state->width;
  cfg.g_h = state->height;
  cfg.g_timebase.num = state->fps_d;
  cfg.g_timebase.den = state->fps_n;

  cfg.g_error_resilient = encoder->error_resilient;
  cfg.g_lag_in_frames = encoder->max_latency;
  cfg.g_threads = encoder->threads;
  cfg.rc_end_usage = encoder->mode;
  cfg.rc_2pass_vbr_minsection_pct = encoder->minsection_pct;
  cfg.rc_2pass_vbr_maxsection_pct = encoder->maxsection_pct;
  /* Standalone qp-min do not make any sence, with bitrate=0 and qp-min=1
   * encoder will use only default qp-max=63. Also this will make
   * worst possbile quality.
   */
  if (encoder->bitrate != DEFAULT_BITRATE ||
      encoder->max_quantizer != DEFAULT_MAX_QUANTIZER) {
    cfg.rc_target_bitrate = encoder->bitrate / 1000;
    cfg.rc_min_quantizer = encoder->min_quantizer;
    cfg.rc_max_quantizer = encoder->max_quantizer;
  } else {
    cfg.rc_min_quantizer = (gint) (63 - encoder->quality * 6.2);
    cfg.rc_max_quantizer = (gint) (63 - encoder->quality * 6.2);
  }
  cfg.rc_dropframe_thresh = encoder->drop_frame;
  cfg.rc_resize_allowed = encoder->resize_allowed;

  cfg.kf_mode = VPX_KF_AUTO;
  cfg.kf_min_dist = 0;
  cfg.kf_max_dist = encoder->max_keyframe_distance;

  cfg.g_pass = encoder->multipass_mode;
  if (encoder->multipass_mode == VPX_RC_FIRST_PASS) {
    encoder->first_pass_cache_content = g_byte_array_sized_new (4096);
  } else if (encoder->multipass_mode == VPX_RC_LAST_PASS) {
    GError *err = NULL;

    if (!encoder->multipass_cache_file) {
      GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
          ("No multipass cache file provided"), (NULL));
      return FALSE;
    }

    if (!g_file_get_contents (encoder->multipass_cache_file,
            (gchar **) & encoder->last_pass_cache_content.buf,
            &encoder->last_pass_cache_content.sz, &err)) {
      GST_ELEMENT_ERROR (encoder, RESOURCE, OPEN_READ,
          ("Failed to read multipass cache file provided"), ("%s",
              err->message));
      g_error_free (err);
      return FALSE;
    }
    cfg.rc_twopass_stats_in = encoder->last_pass_cache_content;
  }

  status = vpx_codec_enc_init (&encoder->encoder, &vpx_codec_vp8_cx_algo,
      &cfg, 0);
  if (status != VPX_CODEC_OK) {
    GST_ELEMENT_ERROR (encoder, LIBRARY, INIT,
        ("Failed to initialize encoder"), ("%s", gst_vpx_error_name (status)));
    return FALSE;
  }

  /* FIXME move this to a set_speed() function */
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_CPUUSED,
      (encoder->speed == 0) ? 0 : (encoder->speed - 1));
  if (status != VPX_CODEC_OK) {
    GST_WARNING_OBJECT (encoder, "Failed to set VP8E_SET_CPUUSED to 0: %s",
        gst_vpx_error_name (status));
  }

  status = vpx_codec_control (&encoder->encoder, VP8E_SET_NOISE_SENSITIVITY,
      encoder->noise_sensitivity);
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_SHARPNESS,
      encoder->sharpness);
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_STATIC_THRESHOLD,
      encoder->static_threshold);
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_TOKEN_PARTITIONS,
      encoder->partitions);
#if 0
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_MAXFRAMES,
      encoder->arnr_maxframes);
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_STRENGTH,
      encoder->arnr_strength);
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_ARNR_TYPE,
      encoder->arnr_type);
#endif
#ifdef HAVE_VP8ENC_TUNING
  status = vpx_codec_control (&encoder->encoder, VP8E_SET_TUNING,
      encoder->tuning);
#endif

  status =
      vpx_codec_control (&encoder->encoder, VP8E_SET_ENABLEAUTOALTREF,
      (encoder->auto_alt_ref_frames ? 1 : 0));
  if (status != VPX_CODEC_OK) {
    GST_WARNING_OBJECT (encoder,
        "Failed to set VP8E_ENABLEAUTOALTREF to %d: %s",
        (encoder->auto_alt_ref_frames ? 1 : 0), gst_vpx_error_name (status));
  }

  cfg.g_lag_in_frames = encoder->lag_in_frames;

  gst_base_video_encoder_set_latency (base_video_encoder, 0,
      gst_util_uint64_scale (encoder->max_latency,
          state->fps_d * GST_SECOND, state->fps_n));
  encoder->inited = TRUE;

  /* prepare cached image buffer setup */
  image = &encoder->image;
  memset (image, 0, sizeof (*image));

  image->fmt = VPX_IMG_FMT_I420;
  image->bps = 12;
  image->x_chroma_shift = image->y_chroma_shift = 1;
  image->w = image->d_w = state->width;
  image->h = image->d_h = state->height;

  image->stride[VPX_PLANE_Y] =
      gst_video_format_get_row_stride (state->format, 0, state->width);
  image->stride[VPX_PLANE_U] =
      gst_video_format_get_row_stride (state->format, 1, state->width);
  image->stride[VPX_PLANE_V] =
      gst_video_format_get_row_stride (state->format, 2, state->width);
  image->planes[VPX_PLANE_Y] =
      data + gst_video_format_get_component_offset (state->format, 0,
      state->width, state->height);
  image->planes[VPX_PLANE_U] =
      data + gst_video_format_get_component_offset (state->format, 1,
      state->width, state->height);
  image->planes[VPX_PLANE_V] =
      data + gst_video_format_get_component_offset (state->format, 2,
      state->width, state->height);


  caps = gst_caps_new_simple ("video/x-vp8",
      "width", G_TYPE_INT, state->width,
      "height", G_TYPE_INT, state->height,
      "framerate", GST_TYPE_FRACTION, state->fps_n,
      state->fps_d,
      "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
      state->par_d, NULL);
  {
    GstStructure *s;
    GstBuffer *stream_hdr, *vorbiscomment;
    const GstTagList *iface_tags;
    GValue array = { 0, };
    GValue value = { 0, };
    s = gst_caps_get_structure (caps, 0);

    /* put buffers in a fixed list */
    g_value_init (&array, GST_TYPE_ARRAY);
    g_value_init (&value, GST_TYPE_BUFFER);

    /* Create Ogg stream-info */
    stream_hdr = gst_buffer_new_and_alloc (26);
    data = GST_BUFFER_DATA (stream_hdr);

    GST_WRITE_UINT8 (data, 0x4F);
    GST_WRITE_UINT32_BE (data + 1, 0x56503830); /* "VP80" */
    GST_WRITE_UINT8 (data + 5, 0x01);   /* stream info header */
    GST_WRITE_UINT8 (data + 6, 1);      /* Major version 1 */
    GST_WRITE_UINT8 (data + 7, 0);      /* Minor version 0 */
    GST_WRITE_UINT16_BE (data + 8, state->width);
    GST_WRITE_UINT16_BE (data + 10, state->height);
    GST_WRITE_UINT24_BE (data + 12, state->par_n);
    GST_WRITE_UINT24_BE (data + 15, state->par_d);
    GST_WRITE_UINT32_BE (data + 18, state->fps_n);
    GST_WRITE_UINT32_BE (data + 22, state->fps_d);

    GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_IN_CAPS);
    gst_value_set_buffer (&value, stream_hdr);
    gst_value_array_append_value (&array, &value);
    g_value_unset (&value);
    gst_buffer_unref (stream_hdr);

    iface_tags =
        gst_tag_setter_get_tag_list (GST_TAG_SETTER (base_video_encoder));
    if (iface_tags) {
      vorbiscomment =
          gst_tag_list_to_vorbiscomment_buffer (iface_tags,
          (const guint8 *) "OVP80\2 ", 7,
          "Encoded with GStreamer vp8enc " PACKAGE_VERSION);

      GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_IN_CAPS);

      g_value_init (&value, GST_TYPE_BUFFER);
      gst_value_set_buffer (&value, vorbiscomment);
      gst_value_array_append_value (&array, &value);
      g_value_unset (&value);
      gst_buffer_unref (vorbiscomment);
    }

    gst_structure_set_value (s, "streamheader", &array);
    g_value_unset (&array);
  }

  ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (encoder), caps);
  gst_caps_unref (caps);

  return ret;
}
Esempio n. 17
0
static GstCaps *
gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
{
  GstCaps *caps;
  const GstVideoState *state;
  GstTagList *tags = NULL;
  const GstTagList *iface_tags;
  GstBuffer *stream_hdr, *vorbiscomment;
  guint8 *data;
  GstStructure *s;
  GValue array = { 0 };
  GValue value = { 0 };

  state = gst_base_video_encoder_get_state (base_video_encoder);

  caps = gst_caps_new_simple ("video/x-vp8",
      "width", G_TYPE_INT, state->width,
      "height", G_TYPE_INT, state->height,
      "framerate", GST_TYPE_FRACTION, state->fps_n,
      state->fps_d,
      "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
      state->par_d, NULL);

  s = gst_caps_get_structure (caps, 0);

  /* put buffers in a fixed list */
  g_value_init (&array, GST_TYPE_ARRAY);
  g_value_init (&value, GST_TYPE_BUFFER);

  /* Create Ogg stream-info */
  stream_hdr = gst_buffer_new_and_alloc (26);
  data = GST_BUFFER_DATA (stream_hdr);

  GST_WRITE_UINT8 (data, 0x4F);
  GST_WRITE_UINT32_BE (data + 1, 0x56503830);   /* "VP80" */
  GST_WRITE_UINT8 (data + 5, 0x01);     /* stream info header */
  GST_WRITE_UINT8 (data + 6, 1);        /* Major version 1 */
  GST_WRITE_UINT8 (data + 7, 0);        /* Minor version 0 */
  GST_WRITE_UINT16_BE (data + 8, state->width);
  GST_WRITE_UINT16_BE (data + 10, state->height);
  GST_WRITE_UINT24_BE (data + 12, state->par_n);
  GST_WRITE_UINT24_BE (data + 15, state->par_d);
  GST_WRITE_UINT32_BE (data + 18, state->fps_n);
  GST_WRITE_UINT32_BE (data + 22, state->fps_d);

  GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_IN_CAPS);
  gst_value_set_buffer (&value, stream_hdr);
  gst_value_array_append_value (&array, &value);
  g_value_unset (&value);
  gst_buffer_unref (stream_hdr);

  iface_tags =
      gst_tag_setter_get_tag_list (GST_TAG_SETTER (base_video_encoder));
  if (iface_tags) {
    vorbiscomment =
        gst_tag_list_to_vorbiscomment_buffer ((iface_tags) ? iface_tags : tags,
        (const guint8 *) "OVP80\2 ", 7,
        "Encoded with GStreamer vp8enc " PACKAGE_VERSION);

    GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_IN_CAPS);

    g_value_init (&value, GST_TYPE_BUFFER);
    gst_value_set_buffer (&value, vorbiscomment);
    gst_value_array_append_value (&array, &value);
    g_value_unset (&value);
    gst_buffer_unref (vorbiscomment);
  }

  gst_structure_set_value (s, "streamheader", &array);
  g_value_unset (&array);

  return caps;
}
Esempio n. 18
0
int main (int argc, char *argv[])
{
  GstElement *bin, *filesrc, *decoder, *encoder, *filesink;
  gchar *artist, *title, *ext, *filename;

  /* initialize GStreamer */
  gst_init (&argc, &argv);
  /* check that the argument is there */
  if (argc != 2) {
    g_print ("usage: %s <mp4 file>\n", argv[0]);
    return 1;
  }
  artist = strrchr (argv[1], '/');
  if (artist == NULL)
    artist = argv[1];
  artist = g_strdup (artist);
  ext = strrchr (artist, '.');
  if (ext)
    *ext = '\0';
  title = strstr (artist, " - ");
  if (title == NULL) {
   return 1;
  }
  *title = '\0';
  title += 3;
  bin = gst_pipeline_new ("pipeline");
  g_assert (bin);

  filesrc = gst_element_factory_make ("filesrc", "disk_source");
  g_assert (filesrc);

  decoder = gst_element_factory_make ("h264dec", "decode");
  if (!decoder) {
    return 1;
  }

  /* create the encoder */
  encoder = gst_element_factory_make ("theoraenc", "encoder");
  if (!encoder) {
    g_print ("cound not find plugin \"theoraenc\"");
	return 1;
  }

  filesink = gst_element_factory_make ("filesink", "filesink");
  g_assert (filesink);
  filename = g_strdup_printf ("%s.ogg", argv[1]);       /* easy solution */
  g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
  g_object_set (G_OBJECT (filesink), "location", filename, NULL);
  g_free (filename);

  gst_tag_setter_set_merge_mode (GST_TAG_SETTER (encoder), GST_TAG_MERGE_KEEP);
  gst_tag_setter_add (GST_TAG_SETTER (encoder), GST_TAG_MERGE_REPLACE,
      GST_TAG_ARTIST, artist, GST_TAG_TITLE, title, NULL);
  gst_bin_add_many (GST_BIN (bin), filesrc, decoder, encoder, filesink, NULL);

  /* link the elements */
  gst_element_link_many (filesrc, decoder, encoder, filesink, NULL);
	
  /* start playing */
  gst_element_set_state (bin, GST_STATE_PLAYING);

  while (gst_bin_iterate (GST_BIN (bin)));

  /* stop the bin */
  gst_element_set_state (bin, GST_STATE_NULL);

  return 0;
}
Esempio n. 19
0
static GstFlowReturn
gst_flac_tag_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
    GstFlacTag *tag;
    GstFlowReturn ret;
    GstMapInfo map;
    gsize size;

    ret = GST_FLOW_OK;
    tag = GST_FLAC_TAG (parent);

    gst_adapter_push (tag->adapter, buffer);

    /* Initial state, we don't even know if we are dealing with a flac file */
    if (tag->state == GST_FLAC_TAG_STATE_INIT) {
        GstBuffer *id_buffer;

        if (gst_adapter_available (tag->adapter) < sizeof (FLAC_MAGIC))
            goto cleanup;

        id_buffer = gst_adapter_take_buffer (tag->adapter, FLAC_MAGIC_SIZE);
        GST_DEBUG_OBJECT (tag, "looking for " FLAC_MAGIC " identifier");
        if (gst_buffer_memcmp (id_buffer, 0, FLAC_MAGIC, FLAC_MAGIC_SIZE) == 0) {

            GST_DEBUG_OBJECT (tag, "pushing " FLAC_MAGIC " identifier buffer");
            ret = gst_pad_push (tag->srcpad, id_buffer);
            if (ret != GST_FLOW_OK)
                goto cleanup;

            tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS;
        } else {
            /* FIXME: does that work well with FLAC files containing ID3v2 tags ? */
            gst_buffer_unref (id_buffer);
            GST_ELEMENT_ERROR (tag, STREAM, WRONG_TYPE, (NULL), (NULL));
            ret = GST_FLOW_ERROR;
        }
    }


    /* The fLaC magic string has been skipped, try to detect the beginning
     * of a metadata block
     */
    if (tag->state == GST_FLAC_TAG_STATE_METADATA_BLOCKS) {
        guint type;
        gboolean is_last;
        const guint8 *block_header;

        g_assert (tag->metadata_block_size == 0);
        g_assert (tag->metadata_last_block == FALSE);

        /* The header of a flac metadata block is 4 bytes long:
         * 1st bit: indicates whether this is the last metadata info block
         * 7 next bits: 4 if vorbis comment block
         * 24 next bits: size of the metadata to follow (big endian)
         */
        if (gst_adapter_available (tag->adapter) < 4)
            goto cleanup;

        block_header = gst_adapter_map (tag->adapter, 4);

        is_last = ((block_header[0] & 0x80) == 0x80);
        type = block_header[0] & 0x7F;
        size = (block_header[1] << 16)
               | (block_header[2] << 8)
               | block_header[3];
        gst_adapter_unmap (tag->adapter);

        /* The 4 bytes long header isn't included in the metadata size */
        tag->metadata_block_size = size + 4;
        tag->metadata_last_block = is_last;

        GST_DEBUG_OBJECT (tag,
                          "got metadata block: %" G_GSIZE_FORMAT " bytes, type %d, "
                          "is vorbiscomment: %d, is last: %d",
                          size, type, (type == 0x04), is_last);

        /* Metadata blocks of type 4 are vorbis comment blocks */
        if (type == 0x04) {
            tag->state = GST_FLAC_TAG_STATE_VC_METADATA_BLOCK;
        } else {
            tag->state = GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK;
        }
    }


    /* Reads a metadata block */
    if ((tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) ||
            (tag->state == GST_FLAC_TAG_STATE_VC_METADATA_BLOCK)) {
        GstBuffer *metadata_buffer;

        if (gst_adapter_available (tag->adapter) < tag->metadata_block_size)
            goto cleanup;

        metadata_buffer = gst_adapter_take_buffer (tag->adapter,
                          tag->metadata_block_size);
        /* clear the is-last flag, as the last metadata block will
         * be the vorbis comment block which we will build ourselves.
         */
        gst_buffer_map (metadata_buffer, &map, GST_MAP_READWRITE);
        map.data[0] &= (~0x80);
        gst_buffer_unmap (metadata_buffer, &map);

        if (tag->state == GST_FLAC_TAG_STATE_WRITING_METADATA_BLOCK) {
            GST_DEBUG_OBJECT (tag, "pushing metadata block buffer");
            ret = gst_pad_push (tag->srcpad, metadata_buffer);
            if (ret != GST_FLOW_OK)
                goto cleanup;
        } else {
            tag->vorbiscomment = metadata_buffer;
        }
        tag->metadata_block_size = 0;
        tag->state = GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK;
    }

    /* This state is mainly used to be able to stop as soon as we read
     * a vorbiscomment block from the flac file if we are in an only output
     * tags mode
     */
    if (tag->state == GST_FLAC_TAG_STATE_METADATA_NEXT_BLOCK) {
        /* Check if in the previous iteration we read a vorbis comment metadata
         * block, and stop now if the user only wants to read tags
         */
        if (tag->vorbiscomment != NULL) {
            guint8 id_data[4];
            /* We found some tags, try to parse them and notify the other elements
             * that we encountered some tags
             */
            GST_DEBUG_OBJECT (tag, "emitting vorbiscomment tags");
            gst_buffer_extract (tag->vorbiscomment, 0, id_data, 4);
            tag->tags = gst_tag_list_from_vorbiscomment_buffer (tag->vorbiscomment,
                        id_data, 4, NULL);
            if (tag->tags != NULL) {
                gst_pad_push_event (tag->srcpad,
                                    gst_event_new_tag (gst_tag_list_copy (tag->tags)));
            }

            gst_buffer_unref (tag->vorbiscomment);
            tag->vorbiscomment = NULL;
        }

        /* Skip to next state */
        if (tag->metadata_last_block == FALSE) {
            tag->state = GST_FLAC_TAG_STATE_METADATA_BLOCKS;
        } else {
            tag->state = GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT;
        }
    }


    /* Creates a vorbis comment block from the metadata which was set
     * on the gstreamer element, and add it to the flac stream
     */
    if (tag->state == GST_FLAC_TAG_STATE_ADD_VORBIS_COMMENT) {
        GstBuffer *buffer;
        const GstTagList *user_tags;
        GstTagList *merged_tags;

        /* merge the tag lists */
        user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tag));
        if (user_tags != NULL) {
            merged_tags = gst_tag_list_merge (user_tags, tag->tags,
                                              gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tag)));
        } else {
            merged_tags = gst_tag_list_copy (tag->tags);
        }

        if (merged_tags == NULL) {
            /* If we get a NULL list of tags, we must generate a padding block
             * which is marked as the last metadata block, otherwise we'll
             * end up with a corrupted flac file.
             */
            GST_WARNING_OBJECT (tag, "No tags found");
            buffer = gst_buffer_new_and_alloc (12);
            if (buffer == NULL)
                goto no_buffer;

            gst_buffer_map (buffer, &map, GST_MAP_WRITE);
            memset (map.data, 0, map.size);
            map.data[0] = 0x81;       /* 0x80 = Last metadata block,
                                 * 0x01 = padding block */
            gst_buffer_unmap (buffer, &map);
        } else {
            guchar header[4];
            guint8 fbit[1];

            memset (header, 0, sizeof (header));
            header[0] = 0x84;         /* 0x80 = Last metadata block,
                                 * 0x04 = vorbiscomment block */
            buffer = gst_tag_list_to_vorbiscomment_buffer (merged_tags, header,
                     sizeof (header), NULL);
            GST_DEBUG_OBJECT (tag, "Writing tags %" GST_PTR_FORMAT, merged_tags);
            gst_tag_list_free (merged_tags);
            if (buffer == NULL)
                goto no_comment;

            size = gst_buffer_get_size (buffer);
            if ((size < 4) || ((size - 4) > 0xFFFFFF))
                goto comment_too_long;

            fbit[0] = 1;
            /* Get rid of the framing bit at the end of the vorbiscomment buffer
             * if it exists since libFLAC seems to lose sync because of this
             * bit in gstflacdec
             */
            if (gst_buffer_memcmp (buffer, size - 1, fbit, 1) == 0) {
                buffer = gst_buffer_make_writable (buffer);
                gst_buffer_resize (buffer, 0, size - 1);
            }
        }

        /* The 4 byte metadata block header isn't accounted for in the total
         * size of the metadata block
         */
        gst_buffer_map (buffer, &map, GST_MAP_WRITE);
        map.data[1] = (((map.size - 4) & 0xFF0000) >> 16);
        map.data[2] = (((map.size - 4) & 0x00FF00) >> 8);
        map.data[3] = ((map.size - 4) & 0x0000FF);
        gst_buffer_unmap (buffer, &map);

        GST_DEBUG_OBJECT (tag, "pushing %" G_GSIZE_FORMAT " byte vorbiscomment "
                          "buffer", map.size);

        ret = gst_pad_push (tag->srcpad, buffer);
        if (ret != GST_FLOW_OK) {
            goto cleanup;
        }
        tag->state = GST_FLAC_TAG_STATE_AUDIO_DATA;
    }
Esempio n. 20
0
static gboolean rc_plugin_tag_mp3_change(const gchar *src_path,
    const gchar *target_path, const GstTagList *tag_list)
{
    GstElement *tag_filesrc = NULL;
    GstElement *tag_filesink = NULL;
    GstElement *tag_demux1 = NULL;
    GstElement *tag_demux2 = NULL;
    GstElement *tag_mux1 = NULL;
    GstElement *tag_mux2 = NULL;
    GstBus *bus = NULL;
    if(src_path==NULL) return FALSE;
    if(target_path==NULL) return FALSE;
    if(tag_list==NULL) return FALSE;
    if(g_access(src_path, W_OK)!=0) return FALSE;
    tag_mux1 = gst_element_factory_make("id3v2mux", "id3v2-tagger");
    tag_mux2 = gst_element_factory_make("apev2mux", "apev2-tagger");
    tag_demux1 = gst_element_factory_make("id3demux", "id3-demux");
    tag_demux2 = gst_element_factory_make("apedemux", "ape-demux");
    if(tag_mux1==NULL || tag_demux1==NULL || tag_demux1==NULL ||
        tag_demux2==NULL)
        goto error_out;
    tag_filesrc = gst_element_factory_make("filesrc", "tag-filesrc");
    if(tag_filesrc==NULL) goto error_out;
    tag_filesink = gst_element_factory_make("filesink", "tag-filesink");
    if(tag_filesink==NULL) goto error_out;
    g_object_set(G_OBJECT(tag_filesrc), "location", src_path, NULL);
    g_object_set(G_OBJECT(tag_filesink), "location", target_path, NULL);
    tagger_pipeline = gst_pipeline_new("tagger-pipeline");
    gst_tag_setter_merge_tags(GST_TAG_SETTER(tag_mux1), tag_list,
        GST_TAG_MERGE_REPLACE);
    gst_tag_setter_merge_tags(GST_TAG_SETTER(tag_mux2), tag_list,
        GST_TAG_MERGE_REPLACE);
    gst_bin_add_many(GST_BIN(tagger_pipeline), tag_filesrc,
        tag_demux2, tag_demux1, tag_mux1, tag_mux2, tag_filesink, NULL);
    g_signal_connect(tag_demux2, "pad-added",
        G_CALLBACK(rc_plugin_tag_writer_pad_added_cb), tag_demux1);
    g_signal_connect(tag_demux1, "pad-added",
        G_CALLBACK(rc_plugin_tag_writer_pad_added_cb), tag_mux1);
    if(!gst_element_link(tag_filesrc, tag_demux1)) goto error_out;
    if(!gst_element_link_many(tag_mux1, tag_mux2, tag_filesink, NULL))
        goto error_out;
    bus = gst_pipeline_get_bus(GST_PIPELINE(tagger_pipeline));
    gst_bus_add_watch(bus, (GstBusFunc)rc_plugin_tag_writer_bus_cb, NULL);
    gst_object_unref(bus);
    gst_element_set_state(tagger_pipeline, GST_STATE_NULL);
    gst_element_set_state(tagger_pipeline, GST_STATE_READY);
    if(gst_element_set_state(tagger_pipeline, GST_STATE_PLAYING)
        ==GST_STATE_CHANGE_FAILURE)
        goto error_out;
    return TRUE;
    error_out:
        if(tag_demux1!=NULL) gst_object_unref(tag_demux1);
        if(tag_mux1!=NULL) gst_object_unref(tag_mux1);
        if(tag_demux2!=NULL) gst_object_unref(tag_demux2);
        if(tag_mux2!=NULL) gst_object_unref(tag_mux2);
        if(tag_filesrc!=NULL) gst_object_unref(tag_filesrc);
        if(tag_filesink!=NULL) gst_object_unref(tag_filesink);
        if(tagger_pipeline!=NULL) gst_object_unref(tagger_pipeline);
        tagger_pipeline = NULL;
        return FALSE;
}
static GstBuffer *
gst_tag_lib_mux_render_tag (GstTagLibMux * mux)
{
  GstTagLibMuxClass *klass;
  GstTagMergeMode merge_mode;
  GstTagSetter *tagsetter;
  GstBuffer *buffer;
  const GstTagList *tagsetter_tags;
  GstTagList *taglist;
  GstEvent *event;

  tagsetter = GST_TAG_SETTER (mux);

  tagsetter_tags = gst_tag_setter_get_tag_list (tagsetter);
  merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter);

  GST_LOG_OBJECT (mux, "merging tags, merge mode = %d", merge_mode);
  GST_LOG_OBJECT (mux, "event tags: %" GST_PTR_FORMAT, mux->event_tags);
  GST_LOG_OBJECT (mux, "set   tags: %" GST_PTR_FORMAT, tagsetter_tags);

  taglist = gst_tag_list_merge (tagsetter_tags, mux->event_tags, merge_mode);

  GST_LOG_OBJECT (mux, "final tags: %" GST_PTR_FORMAT, taglist);

  klass = GST_TAG_LIB_MUX_CLASS (G_OBJECT_GET_CLASS (mux));

  if (klass->render_tag == NULL)
    goto no_vfunc;

  buffer = klass->render_tag (mux, taglist);

  if (buffer == NULL)
    goto render_error;

  mux->tag_size = GST_BUFFER_SIZE (buffer);
  GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes", mux->tag_size);

  /* Send newsegment event from byte position 0, so the tag really gets
   * written to the start of the file, independent of the upstream segment */
  gst_pad_push_event (mux->srcpad,
      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));

  /* Send an event about the new tags to downstream elements */
  /* gst_event_new_tag takes ownership of the list, so no need to unref it */
  event = gst_event_new_tag (taglist);
  gst_pad_push_event (mux->srcpad, event);

  GST_BUFFER_OFFSET (buffer) = 0;

  return buffer;

no_vfunc:
  {
    GST_ERROR_OBJECT (mux, "Subclass does not implement render_tag vfunc!");
    gst_tag_list_free (taglist);
    return NULL;
  }

render_error:
  {
    GST_ERROR_OBJECT (mux, "Failed to render tag");
    gst_tag_list_free (taglist);
    return NULL;
  }
}
Esempio n. 22
0
static void
gst_vp8_enc_set_stream_info (GstVPXEnc * enc, GstCaps * caps,
    GstVideoInfo * info)
{
  GstStructure *s;
  GstVideoEncoder *video_encoder;
  GstBuffer *stream_hdr, *vorbiscomment;
  const GstTagList *iface_tags;
  GValue array = { 0, };
  GValue value = { 0, };
  guint8 *data = NULL;
  GstMapInfo map;

  video_encoder = GST_VIDEO_ENCODER (enc);
  s = gst_caps_get_structure (caps, 0);

  /* put buffers in a fixed list */
  g_value_init (&array, GST_TYPE_ARRAY);
  g_value_init (&value, GST_TYPE_BUFFER);

  /* Create Ogg stream-info */
  stream_hdr = gst_buffer_new_and_alloc (26);
  gst_buffer_map (stream_hdr, &map, GST_MAP_WRITE);
  data = map.data;

  GST_WRITE_UINT8 (data, 0x4F);
  GST_WRITE_UINT32_BE (data + 1, 0x56503830);   /* "VP80" */
  GST_WRITE_UINT8 (data + 5, 0x01);     /* stream info header */
  GST_WRITE_UINT8 (data + 6, 1);        /* Major version 1 */
  GST_WRITE_UINT8 (data + 7, 0);        /* Minor version 0 */
  GST_WRITE_UINT16_BE (data + 8, GST_VIDEO_INFO_WIDTH (info));
  GST_WRITE_UINT16_BE (data + 10, GST_VIDEO_INFO_HEIGHT (info));
  GST_WRITE_UINT24_BE (data + 12, GST_VIDEO_INFO_PAR_N (info));
  GST_WRITE_UINT24_BE (data + 15, GST_VIDEO_INFO_PAR_D (info));
  GST_WRITE_UINT32_BE (data + 18, GST_VIDEO_INFO_FPS_N (info));
  GST_WRITE_UINT32_BE (data + 22, GST_VIDEO_INFO_FPS_D (info));

  gst_buffer_unmap (stream_hdr, &map);

  GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_HEADER);
  gst_value_set_buffer (&value, stream_hdr);
  gst_value_array_append_value (&array, &value);
  g_value_unset (&value);
  gst_buffer_unref (stream_hdr);

  iface_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (video_encoder));
  if (iface_tags) {
    vorbiscomment =
        gst_tag_list_to_vorbiscomment_buffer (iface_tags,
        (const guint8 *) "OVP80\2 ", 7,
        "Encoded with GStreamer vp8enc " PACKAGE_VERSION);

    GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_HEADER);

    g_value_init (&value, GST_TYPE_BUFFER);
    gst_value_set_buffer (&value, vorbiscomment);
    gst_value_array_append_value (&array, &value);
    g_value_unset (&value);
    gst_buffer_unref (vorbiscomment);
  }

  gst_structure_set_value (s, "streamheader", &array);
  g_value_unset (&array);

}
Esempio n. 23
0
static GstFlowReturn
gst_ffmpegmux_collected (GstCollectPads * pads, gpointer user_data)
{
  GstFFMpegMux *ffmpegmux = (GstFFMpegMux *) user_data;
  GSList *collected;
  GstFFMpegMuxPad *best_pad;
  GstClockTime best_time;
  const GstTagList *tags;

  /* open "file" (gstreamer protocol to next element) */
  if (!ffmpegmux->opened) {
    int open_flags = URL_WRONLY;

    /* we do need all streams to have started capsnego,
     * or things will go horribly wrong */
    for (collected = ffmpegmux->collect->data; collected;
        collected = g_slist_next (collected)) {
      GstFFMpegMuxPad *collect_pad = (GstFFMpegMuxPad *) collected->data;
      AVStream *st = ffmpegmux->context->streams[collect_pad->padnum];

      /* check whether the pad has successfully completed capsnego */
      if (st->codec->codec_id == CODEC_ID_NONE) {
        GST_ELEMENT_ERROR (ffmpegmux, CORE, NEGOTIATION, (NULL),
            ("no caps set on stream %d (%s)", collect_pad->padnum,
                (st->codec->codec_type == CODEC_TYPE_VIDEO) ?
                "video" : "audio"));
        return GST_FLOW_ERROR;
      }
      /* set framerate for audio */
      if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
        switch (st->codec->codec_id) {
          case CODEC_ID_PCM_S16LE:
          case CODEC_ID_PCM_S16BE:
          case CODEC_ID_PCM_U16LE:
          case CODEC_ID_PCM_U16BE:
          case CODEC_ID_PCM_S8:
          case CODEC_ID_PCM_U8:
            st->codec->frame_size = 1;
            break;
          default:
          {
            GstBuffer *buffer;

            /* FIXME : This doesn't work for RAW AUDIO...
             * in fact I'm wondering if it even works for any kind of audio... */
            buffer = gst_collect_pads_peek (ffmpegmux->collect,
                (GstCollectData *) collect_pad);
            if (buffer) {
              st->codec->frame_size =
                  st->codec->sample_rate *
                  GST_BUFFER_DURATION (buffer) / GST_SECOND;
              gst_buffer_unref (buffer);
            }
          }
        }
      }
    }

    /* tags */
    tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (ffmpegmux));
    if (tags) {
      gint i;
      gchar *s;

      /* get the interesting ones */
      if (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s)) {
        strncpy (ffmpegmux->context->title, s,
            sizeof (ffmpegmux->context->title));
      }
      if (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s)) {
        strncpy (ffmpegmux->context->author, s,
            sizeof (ffmpegmux->context->author));
      }
      if (gst_tag_list_get_string (tags, GST_TAG_COPYRIGHT, &s)) {
        strncpy (ffmpegmux->context->copyright, s,
            sizeof (ffmpegmux->context->copyright));
      }
      if (gst_tag_list_get_string (tags, GST_TAG_COMMENT, &s)) {
        strncpy (ffmpegmux->context->comment, s,
            sizeof (ffmpegmux->context->comment));
      }
      if (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s)) {
        strncpy (ffmpegmux->context->album, s,
            sizeof (ffmpegmux->context->album));
      }
      if (gst_tag_list_get_string (tags, GST_TAG_GENRE, &s)) {
        strncpy (ffmpegmux->context->genre, s,
            sizeof (ffmpegmux->context->genre));
      }
      if (gst_tag_list_get_int (tags, GST_TAG_TRACK_NUMBER, &i)) {
        ffmpegmux->context->track = i;
      }
    }

    /* set the streamheader flag for gstffmpegprotocol if codec supports it */
    if (!strcmp (ffmpegmux->context->oformat->name, "flv")) {
      open_flags |= GST_FFMPEG_URL_STREAMHEADER;
    }

    if (url_fopen (&ffmpegmux->context->pb,
            ffmpegmux->context->filename, open_flags) < 0) {
      GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, TOO_LAZY, (NULL),
          ("Failed to open stream context in ffmux"));
      return GST_FLOW_ERROR;
    }

    if (av_set_parameters (ffmpegmux->context, NULL) < 0) {
      GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, INIT, (NULL),
          ("Failed to initialize muxer"));
      return GST_FLOW_ERROR;
    }

    /* now open the mux format */
    if (av_write_header (ffmpegmux->context) < 0) {
      GST_ELEMENT_ERROR (ffmpegmux, LIBRARY, SETTINGS, (NULL),
          ("Failed to write file header - check codec settings"));
      return GST_FLOW_ERROR;
    }

    /* we're now opened */
    ffmpegmux->opened = TRUE;

    /* flush the header so it will be used as streamheader */
    put_flush_packet (ffmpegmux->context->pb);
  }

  /* take the one with earliest timestamp,
   * and push it forward */
  best_pad = NULL;
  best_time = GST_CLOCK_TIME_NONE;
  for (collected = ffmpegmux->collect->data; collected;
      collected = g_slist_next (collected)) {
    GstFFMpegMuxPad *collect_pad = (GstFFMpegMuxPad *) collected->data;
    GstBuffer *buffer = gst_collect_pads_peek (ffmpegmux->collect,
        (GstCollectData *) collect_pad);

    /* if there's no buffer, just continue */
    if (buffer == NULL) {
      continue;
    }

    /* if we have no buffer yet, just use the first one */
    if (best_pad == NULL) {
      best_pad = collect_pad;
      best_time = GST_BUFFER_TIMESTAMP (buffer);
      goto next_pad;
    }

    /* if we do have one, only use this one if it's older */
    if (GST_BUFFER_TIMESTAMP (buffer) < best_time) {
      best_time = GST_BUFFER_TIMESTAMP (buffer);
      best_pad = collect_pad;
    }

  next_pad:
    gst_buffer_unref (buffer);

    /* Mux buffers with invalid timestamp first */
    if (!GST_CLOCK_TIME_IS_VALID (best_time))
      break;
  }

  /* now handle the buffer, or signal EOS if we have
   * no buffers left */
  if (best_pad != NULL) {
    GstBuffer *buf;
    AVPacket pkt;
    gboolean need_free = FALSE;

    /* push out current buffer */
    buf = gst_collect_pads_pop (ffmpegmux->collect,
        (GstCollectData *) best_pad);

    ffmpegmux->context->streams[best_pad->padnum]->codec->frame_number++;

    /* set time */
    pkt.pts = gst_ffmpeg_time_gst_to_ff (GST_BUFFER_TIMESTAMP (buf),
        ffmpegmux->context->streams[best_pad->padnum]->time_base);
    pkt.dts = pkt.pts;

    if (strcmp (ffmpegmux->context->oformat->name, "gif") == 0) {
      AVStream *st = ffmpegmux->context->streams[best_pad->padnum];
      AVPicture src, dst;

      need_free = TRUE;
      pkt.size = st->codec->width * st->codec->height * 3;
      pkt.data = g_malloc (pkt.size);

      dst.data[0] = pkt.data;
      dst.data[1] = NULL;
      dst.data[2] = NULL;
      dst.linesize[0] = st->codec->width * 3;

      gst_ffmpeg_avpicture_fill (&src, GST_BUFFER_DATA (buf),
          PIX_FMT_RGB24, st->codec->width, st->codec->height);

      av_picture_copy (&dst, &src, PIX_FMT_RGB24,
          st->codec->width, st->codec->height);
    } else {
      pkt.data = GST_BUFFER_DATA (buf);
      pkt.size = GST_BUFFER_SIZE (buf);
    }

    pkt.stream_index = best_pad->padnum;
    pkt.flags = 0;

    if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT))
      pkt.flags |= PKT_FLAG_KEY;

    if (GST_BUFFER_DURATION_IS_VALID (buf))
      pkt.duration =
          gst_ffmpeg_time_gst_to_ff (GST_BUFFER_DURATION (buf),
          ffmpegmux->context->streams[best_pad->padnum]->time_base);
    else
      pkt.duration = 0;
    av_write_frame (ffmpegmux->context, &pkt);
    gst_buffer_unref (buf);
    if (need_free)
      g_free (pkt.data);
  } else {
    /* close down */
    av_write_trailer (ffmpegmux->context);
    ffmpegmux->opened = FALSE;
    put_flush_packet (ffmpegmux->context->pb);
    url_fclose (ffmpegmux->context->pb);
    gst_pad_push_event (ffmpegmux->srcpad, gst_event_new_eos ());
    return GST_FLOW_UNEXPECTED;
  }

  return GST_FLOW_OK;
}
Esempio n. 24
0
static gboolean
gst_kate_enc_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstKateEnc *ke = GST_KATE_ENC (parent);
  const GstStructure *structure;
  gboolean ret;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_kate_enc_setcaps (ke, caps);
      gst_event_unref (event);
      break;
    }
    case GST_EVENT_SEGMENT:{
      GstSegment seg;

      GST_LOG_OBJECT (ke, "Got newsegment event");

      gst_event_copy_segment (event, &seg);

      if (!ke->headers_sent) {
        if (ke->pending_segment)
          gst_event_unref (ke->pending_segment);
        ke->pending_segment = event;
        event = NULL;
      }

      if (ke->initialized) {
        GST_LOG_OBJECT (ke, "ensuring all headers are in");
        if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
          GST_WARNING_OBJECT (ke, "Failed to flush headers");
        } else {
          if (seg.format != GST_FORMAT_TIME
              || !GST_CLOCK_TIME_IS_VALID (seg.start)) {
            GST_WARNING_OBJECT (ke,
                "No time in newsegment event %p, format %d, timestamp %"
                G_GINT64_FORMAT, event, (int) seg.format, seg.start);
            /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a
               good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a
               timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we
               run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */
          } else {
            float t = seg.start / (double) GST_SECOND;

            if (ke->delayed_spu
                && t - ke->delayed_start / (double) GST_SECOND >=
                ke->default_spu_duration) {
              if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke,
                          seg.start) != GST_FLOW_OK)) {
                GST_WARNING_OBJECT (ke, "Failed to encode delayed packet");
                /* continue with new segment handling anyway */
              }
            }

            GST_LOG_OBJECT (ke, "ts %f, last %f (min %f)", t,
                ke->last_timestamp / (double) GST_SECOND,
                ke->keepalive_min_time);
            if (ke->keepalive_min_time > 0.0f
                && t - ke->last_timestamp / (double) GST_SECOND >=
                ke->keepalive_min_time) {
              /* we only generate a keepalive if there is no SPU waiting, as it would
                 mean out of sequence start times - and granulepos */
              if (!ke->delayed_spu) {
                gst_kate_enc_generate_keepalive (ke, seg.start);
              }
            }
          }
        }
      }
      if (event)
        ret = gst_pad_push_event (ke->srcpad, event);
      else
        ret = TRUE;
      break;
    }
    case GST_EVENT_CUSTOM_DOWNSTREAM:
      GST_LOG_OBJECT (ke, "Got custom downstream event");
      /* adapted from the dvdsubdec element */
      structure = gst_event_get_structure (event);
      if (structure != NULL
          && gst_structure_has_name (structure, "application/x-gst-dvd")) {
        if (ke->initialized) {
          GST_LOG_OBJECT (ke, "ensuring all headers are in");
          if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
            GST_WARNING_OBJECT (ke, "Failed to flush headers");
          } else {
            const gchar *event_name =
                gst_structure_get_string (structure, "event");
            if (event_name) {
              if (!strcmp (event_name, "dvd-spu-clut-change")) {
                gchar name[16];
                int idx;
                gboolean found;
                gint value;
                GST_INFO_OBJECT (ke, "New CLUT received");
                for (idx = 0; idx < 16; ++idx) {
                  g_snprintf (name, sizeof (name), "clut%02d", idx);
                  found = gst_structure_get_int (structure, name, &value);
                  if (found) {
                    ke->spu_clut[idx] = value;
                  } else {
                    GST_WARNING_OBJECT (ke,
                        "DVD CLUT event did not contain %s field", name);
                  }
                }
              } else if (!strcmp (event_name, "dvd-lang-codes")) {
                /* we can't know which stream corresponds to us */
              }
            } else {
              GST_WARNING_OBJECT (ke, "custom downstream event with no name");
            }
          }
        }
      }
      ret = gst_pad_push_event (ke->srcpad, event);
      break;

    case GST_EVENT_TAG:
      GST_LOG_OBJECT (ke, "Got tag event");
      if (ke->tags) {
        GstTagList *list;

        gst_event_parse_tag (event, &list);
        gst_tag_list_insert (ke->tags, list,
            gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke)));
      } else {
        g_assert_not_reached ();
      }
      ret = gst_pad_event_default (pad, parent, event);
      break;

    case GST_EVENT_EOS:
      GST_INFO_OBJECT (ke, "Got EOS event");
      if (ke->initialized) {
        GST_LOG_OBJECT (ke, "ensuring all headers are in");
        if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
          GST_WARNING_OBJECT (ke, "Failed to flush headers");
        } else {
          kate_packet kp;
          int ret;
          GstClockTime delayed_end =
              ke->delayed_start + ke->default_spu_duration * GST_SECOND;

          if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke,
                      delayed_end) != GST_FLOW_OK)) {
            GST_WARNING_OBJECT (ke, "Failed to encode delayed packet");
            /* continue with EOS handling anyway */
          }

          ret = kate_encode_finish (&ke->k, -1, &kp);
          if (ret < 0) {
            GST_WARNING_OBJECT (ke, "Failed to encode EOS packet: %s",
                gst_kate_util_get_error_message (ret));
          } else {
            kate_int64_t granpos = kate_encode_get_granule (&ke->k);
            GST_LOG_OBJECT (ke, "EOS packet encoded");
            if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos,
                    ke->latest_end_time, 0, FALSE)) {
              GST_WARNING_OBJECT (ke, "Failed to push EOS packet");
            }
          }
        }
      }
      ret = gst_pad_event_default (pad, parent, event);
      break;

    default:
      GST_LOG_OBJECT (ke, "Got unhandled event");
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }

  return ret;
}
Esempio n. 25
0
static void
test_taglib_id3mux_with_tags (GstTagList * tags, guint32 mask)
{
    GstMessage *msg;
    GstTagList *tags_read = NULL;
    GstElement *pipeline, *id3mux, *id3demux, *fakesrc, *identity, *fakesink;
    GstBus *bus;
    guint64 offset;
    GstBuffer *outbuf = NULL;
    GstBuffer *tagbuf = NULL;
    GstStateChangeReturn state_result;

    pipeline = gst_pipeline_new ("pipeline");
    g_assert (pipeline != NULL);

    fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
    g_assert (fakesrc != NULL);

    id3mux = gst_element_factory_make ("id3v2mux", "id3v2mux");
    g_assert (id3mux != NULL);

    identity = gst_element_factory_make ("identity", "identity");
    g_assert (identity != NULL);

    id3demux = gst_element_factory_make ("id3demux", "id3demux");
    g_assert (id3demux != NULL);

    fakesink = gst_element_factory_make ("fakesink", "fakesink");
    g_assert (fakesink != NULL);

    /* set up sink */
    outbuf = NULL;
    g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
    g_signal_connect (fakesink, "handoff", G_CALLBACK (got_buffer), &outbuf);

    gst_bin_add (GST_BIN (pipeline), fakesrc);
    gst_bin_add (GST_BIN (pipeline), id3mux);
    gst_bin_add (GST_BIN (pipeline), identity);
    gst_bin_add (GST_BIN (pipeline), id3demux);
    gst_bin_add (GST_BIN (pipeline), fakesink);

    gst_tag_setter_merge_tags (GST_TAG_SETTER (id3mux), tags,
                               GST_TAG_MERGE_APPEND);

    gst_element_link_many (fakesrc, id3mux, identity, id3demux, fakesink, NULL);

    /* set up source */
    g_object_set (fakesrc, "signal-handoffs", TRUE, "can-activate-pull", FALSE,
                  "filltype", 2, "sizetype", 2, "sizemax", MP3_FRAME_SIZE,
                  "num-buffers", 16, NULL);

    offset = 0;
    g_signal_connect (fakesrc, "handoff", G_CALLBACK (fill_mp3_buffer), &offset);

    /* set up identity to catch tag buffer */
    g_signal_connect (identity, "handoff", G_CALLBACK (identity_cb), &tagbuf);

    GST_LOG ("setting and getting state ...");
    gst_element_set_state (pipeline, GST_STATE_PLAYING);
    state_result = gst_element_get_state (pipeline, NULL, NULL, -1);
    fail_unless (state_result == GST_STATE_CHANGE_SUCCESS,
                 "Unexpected result from get_state(). Expected success, got %d",
                 state_result);

    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));

    GST_LOG ("Waiting for tag ...");
    msg =
        gst_bus_poll (bus, GST_MESSAGE_TAG | GST_MESSAGE_EOS | GST_MESSAGE_ERROR,
                      -1);
    if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        GError *err;
        gchar *dbg;

        gst_message_parse_error (msg, &err, &dbg);
        g_printerr ("ERROR from element %s: %s\n%s\n",
                    GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
        g_error_free (err);
        g_free (dbg);
    } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
        g_printerr ("EOS message, but were waiting for TAGS!\n");
    }
    fail_unless (msg->type == GST_MESSAGE_TAG);

    gst_message_parse_tag (msg, &tags_read);
    gst_message_unref (msg);

    GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags_read);
    test_taglib_id3mux_check_tags (tags_read, mask);
    gst_tag_list_unref (tags_read);

    fail_unless (tagbuf != NULL);
    test_taglib_id3mux_check_tag_buffer (tagbuf, mask);
    gst_buffer_unref (tagbuf);

    GST_LOG ("Waiting for EOS ...");
    msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
    if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        GError *err;
        gchar *dbg;

        gst_message_parse_error (msg, &err, &dbg);
        g_printerr ("ERROR from element %s: %s\n%s\n",
                    GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
        g_error_free (err);
        g_free (dbg);
    }
    fail_unless (msg->type == GST_MESSAGE_EOS);
    gst_message_unref (msg);

    gst_object_unref (bus);

    GST_LOG ("Got EOS, shutting down ...");
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);

    test_taglib_id3mux_check_output_buffer (outbuf);
    gst_buffer_unref (outbuf);

    GST_LOG ("Done");
}
Esempio n. 26
0
static gboolean
gst_jif_mux_mangle_markers (GstJifMux * self)
{
    gboolean modified = FALSE;
    GstTagList *tags = NULL;
    gboolean cleanup_tags;
    GstJifMuxMarker *m;
    GList *node, *file_hdr = NULL, *frame_hdr = NULL, *scan_hdr = NULL;
    GList *app0_jfif = NULL, *app1_exif = NULL, *app1_xmp = NULL, *com = NULL;
    GstBuffer *xmp_data;
    gchar *str = NULL;
    gint colorspace = COLORSPACE_UNKNOWN;

    /* update the APP markers
     * - put any JFIF APP0 first
     * - the Exif APP1 next,
     * - the XMP APP1 next,
     * - the PSIR APP13 next,
     * - followed by all other marker segments
     */

    /* find some reference points where we insert before/after */
    file_hdr = self->priv->markers;
    for (node = self->priv->markers; node; node = g_list_next (node)) {
        m = (GstJifMuxMarker *) node->data;

        switch (m->marker) {
        case APP0:
            if (m->size > 5 && !memcmp (m->data, "JFIF\0", 5)) {
                GST_DEBUG_OBJECT (self, "found APP0 JFIF");
                colorspace |= COLORSPACE_GRAYSCALE | COLORSPACE_YUV;
                if (!app0_jfif)
                    app0_jfif = node;
            }
            break;
        case APP1:
            if (m->size > 6 && (!memcmp (m->data, "EXIF\0\0", 6) ||
                                !memcmp (m->data, "Exif\0\0", 6))) {
                GST_DEBUG_OBJECT (self, "found APP1 EXIF");
                if (!app1_exif)
                    app1_exif = node;
            } else if (m->size > 29
                       && !memcmp (m->data, "http://ns.adobe.com/xap/1.0/\0", 29)) {
                GST_INFO_OBJECT (self, "found APP1 XMP, will be replaced");
                if (!app1_xmp)
                    app1_xmp = node;
            }
            break;
        case APP14:
            /* check if this contains RGB */
            /*
             * This marker should have:
             * - 'Adobe\0'
             * - 2 bytes DCTEncodeVersion
             * - 2 bytes flags0
             * - 2 bytes flags1
             * - 1 byte  ColorTransform
             *             - 0 means unknown (RGB or CMYK)
             *             - 1 YCbCr
             *             - 2 YCCK
             */

            if ((m->size >= 14)
                    && (strncmp ((gchar *) m->data, "Adobe\0", 6) == 0)) {
                switch (m->data[11]) {
                case 0:
                    colorspace |= COLORSPACE_RGB | COLORSPACE_CMYK;
                    break;
                case 1:
                    colorspace |= COLORSPACE_YUV;
                    break;
                case 2:
                    colorspace |= COLORSPACE_YCCK;
                    break;
                default:
                    break;
                }
            }

            break;
        case COM:
            GST_INFO_OBJECT (self, "found COM, will be replaced");
            if (!com)
                com = node;
            break;
        case DQT:
        case SOF0:
        case SOF1:
        case SOF2:
        case SOF3:
        case SOF5:
        case SOF6:
        case SOF7:
        case SOF9:
        case SOF10:
        case SOF11:
        case SOF13:
        case SOF14:
        case SOF15:
            if (!frame_hdr)
                frame_hdr = node;
            break;
        case DAC:
        case DHT:
        case DRI:
        case SOS:
            if (!scan_hdr)
                scan_hdr = node;
            break;
        }
    }

    /* if we want combined or JFIF */
    /* check if we don't have JFIF APP0 */
    if (!app0_jfif && (colorspace & (COLORSPACE_GRAYSCALE | COLORSPACE_YUV))) {
        /* build jfif header */
        static const struct
        {
            gchar id[5];
            guint8 ver[2];
            guint8 du;
            guint8 xd[2], yd[2];
            guint8 tw, th;
        } jfif_data = {
            "JFIF", {
                1, 2
            }, 0, {
                0, 1
            },                    /* FIXME: check pixel-aspect from caps */
            {
                0, 1
            }, 0, 0
        };
        m = gst_jif_mux_new_marker (APP0, sizeof (jfif_data),
                                    (const guint8 *) &jfif_data, FALSE);
        /* insert into self->markers list */
        self->priv->markers = g_list_insert (self->priv->markers, m, 1);
        app0_jfif = g_list_nth (self->priv->markers, 1);
    }
    /* else */
    /* remove JFIF if exists */

    /* Existing exif tags will be removed and our own will be added */
    if (!tags) {
        tags = (GstTagList *) gst_tag_setter_get_tag_list (GST_TAG_SETTER (self));
        cleanup_tags = FALSE;
    }
    if (!tags) {
        tags = gst_tag_list_new ();
        cleanup_tags = TRUE;
    }

    GST_DEBUG_OBJECT (self, "Tags to be serialized %" GST_PTR_FORMAT, tags);

    /* FIXME: not happy with those
     * - else where we would use VIDEO_CODEC = "Jpeg"
     gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
     GST_TAG_VIDEO_CODEC, "image/jpeg", NULL);
     */

    /* Add EXIF */
    {
        GstBuffer *exif_data;
        guint8 *data;
        GstJifMuxMarker *m;
        GList *pos;

        /* insert into self->markers list */
        exif_data = gst_tag_list_to_exif_buffer_with_tiff_header (tags);
        if (exif_data &&
                GST_BUFFER_SIZE (exif_data) + 8 >= G_GUINT64_CONSTANT (65536)) {
            GST_WARNING_OBJECT (self, "Exif tags data size exceed maximum size");
            gst_buffer_unref (exif_data);
            exif_data = NULL;
        }
        if (exif_data) {
            data = g_malloc0 (GST_BUFFER_SIZE (exif_data) + 6);
            memcpy (data, "Exif", 4);
            memcpy (data + 6, GST_BUFFER_DATA (exif_data),
                    GST_BUFFER_SIZE (exif_data));
            m = gst_jif_mux_new_marker (APP1, GST_BUFFER_SIZE (exif_data) + 6, data,
                                        TRUE);
            gst_buffer_unref (exif_data);

            if (app1_exif) {
                gst_jif_mux_marker_free ((GstJifMuxMarker *) app1_exif->data);
                app1_exif->data = m;
            } else {
                pos = file_hdr;
                if (app0_jfif)
                    pos = app0_jfif;
                pos = g_list_next (pos);

                self->priv->markers =
                    g_list_insert_before (self->priv->markers, pos, m);
                if (pos) {
                    app1_exif = g_list_previous (pos);
                } else {
                    app1_exif = g_list_last (self->priv->markers);
                }
            }
            modified = TRUE;
        }
    }

    /* add xmp */
    xmp_data =
        gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (self),
                tags, FALSE);
    if (xmp_data) {
        guint8 *data, *xmp = GST_BUFFER_DATA (xmp_data);
        guint size = GST_BUFFER_SIZE (xmp_data);
        GList *pos;

        data = g_malloc (size + 29);
        memcpy (data, "http://ns.adobe.com/xap/1.0/\0", 29);
        memcpy (&data[29], xmp, size);
        m = gst_jif_mux_new_marker (APP1, size + 29, data, TRUE);

        /*
         * Replace the old xmp marker and not add a new one.
         * There shouldn't be a xmp packet in the input, but it is better
         * to be safe than add another one and end up with 2 packets.
         */
        if (app1_xmp) {
            gst_jif_mux_marker_free ((GstJifMuxMarker *) app1_xmp->data);
            app1_xmp->data = m;
        } else {

            pos = file_hdr;
            if (app1_exif)
                pos = app1_exif;
            else if (app0_jfif)
                pos = app0_jfif;
            pos = g_list_next (pos);

            self->priv->markers = g_list_insert_before (self->priv->markers, pos, m);

        }
        gst_buffer_unref (xmp_data);
        modified = TRUE;
    }

    /* add jpeg comment from any of those */
    (void) (gst_tag_list_get_string (tags, GST_TAG_COMMENT, &str) ||
            gst_tag_list_get_string (tags, GST_TAG_DESCRIPTION, &str) ||
            gst_tag_list_get_string (tags, GST_TAG_TITLE, &str));

    if (str) {
        GST_DEBUG_OBJECT (self, "set COM marker to '%s'", str);
        /* insert new marker into self->markers list */
        m = gst_jif_mux_new_marker (COM, strlen (str) + 1, (const guint8 *) str,
                                    TRUE);
        /* FIXME: if we have one already, replace */
        /* this should go before SOS, maybe at the end of file-header */
        self->priv->markers = g_list_insert_before (self->priv->markers,
                              frame_hdr, m);

        modified = TRUE;
    }

    if (tags && cleanup_tags)
        gst_tag_list_free (tags);
    return modified;
}
Esempio n. 27
0
static void
test_tags (const gchar * tag_str)
{
  GstElement *pipeline;
  GstBus *bus;
  GMainLoop *loop;
  GstTagList *sent_tags;
  gint i, j, n_recv, n_sent;
  const gchar *name_sent, *name_recv;
  const GValue *value_sent, *value_recv;
  gboolean found, ok;
  gint comparison;
  GstElement *videotestsrc, *jpegenc, *metadatamux, *metadatademux, *fakesink;
  GstTagSetter *setter;

  GST_DEBUG ("testing tags : %s", tag_str);

  if (received_tags) {
    gst_tag_list_free (received_tags);
    received_tags = NULL;
  }

  pipeline = gst_pipeline_new ("pipeline");
  fail_unless (pipeline != NULL);

  videotestsrc = gst_element_factory_make ("videotestsrc", "src");
  fail_unless (videotestsrc != NULL);
  g_object_set (G_OBJECT (videotestsrc), "num-buffers", 1, NULL);

  jpegenc = gst_element_factory_make ("jpegenc", "enc");
  if (jpegenc == NULL) {
    g_print ("Cannot test - jpegenc not available\n");
    return;
  }

  metadatamux = gst_element_factory_make ("metadatamux", "mux");
  g_object_set (G_OBJECT (metadatamux), "exif", TRUE, NULL);
  fail_unless (metadatamux != NULL);

  metadatademux = gst_element_factory_make ("metadatademux", "demux");
  fail_unless (metadatademux != NULL);

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

  gst_bin_add_many (GST_BIN (pipeline), videotestsrc, jpegenc, metadatamux,
      metadatademux, fakesink, NULL);

  ok = gst_element_link_many (videotestsrc, jpegenc, metadatamux, metadatademux,
      fakesink, NULL);
  fail_unless (ok == TRUE);

  loop = g_main_loop_new (NULL, TRUE);
  fail_unless (loop != NULL);

  bus = gst_element_get_bus (pipeline);
  fail_unless (bus != NULL);
  gst_bus_add_watch (bus, bus_handler, loop);
  gst_object_unref (bus);

  gst_element_set_state (pipeline, GST_STATE_READY);

  setter = GST_TAG_SETTER (metadatamux);
  fail_unless (setter != NULL);
  sent_tags = gst_structure_from_string (tag_str, NULL);
  fail_unless (sent_tags != NULL);
  gst_tag_setter_merge_tags (setter, sent_tags, GST_TAG_MERGE_REPLACE);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  g_main_loop_run (loop);

  GST_DEBUG ("mainloop done : %p", received_tags);

  /* verify tags */
  fail_unless (received_tags != NULL);
  n_recv = gst_structure_n_fields (received_tags);
  n_sent = gst_structure_n_fields (sent_tags);
  /* we also get e.g. an exif binary block */
  fail_unless (n_recv >= n_sent);
  /* FIXME: compare taglits values */
  for (i = 0; i < n_sent; i++) {
    name_sent = gst_structure_nth_field_name (sent_tags, i);
    value_sent = gst_structure_get_value (sent_tags, name_sent);
    found = FALSE;
    for (j = 0; j < n_recv; j++) {
      name_recv = gst_structure_nth_field_name (received_tags, j);
      if (!strcmp (name_sent, name_recv)) {
        value_recv = gst_structure_get_value (received_tags, name_recv);
        comparison = gst_value_compare (value_sent, value_recv);
        if (comparison != GST_VALUE_EQUAL) {
          gchar *vs = g_strdup_value_contents (value_sent);
          gchar *vr = g_strdup_value_contents (value_recv);
          GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
              G_VALUE_TYPE_NAME (value_sent), vs,
              G_VALUE_TYPE_NAME (value_recv), vr);
          g_free (vs);
          g_free (vr);
        }
        fail_unless (comparison == GST_VALUE_EQUAL,
            "tag item %s has been received with different type or value",
            name_sent);
        found = TRUE;
        break;
      }
    }
    fail_unless (found, "tag item %s is lost", name_sent);
  }

  gst_tag_list_free (received_tags);
  received_tags = NULL;
  gst_tag_list_free (sent_tags);

  gst_element_set_state (pipeline, GST_STATE_NULL);

  g_main_loop_unref (loop);
  g_object_unref (pipeline);
}
Esempio n. 28
0
gboolean	ly_mdh_push(LyMdhMetadata *md)
{
	if(!md||!g_str_has_prefix(md->uri, "file://"))
		return FALSE;
	
	if(!g_mutex_trylock(ly_mdh_put_mutex))
	{
		ly_log_put_with_flag(G_LOG_LEVEL_WARNING, _("An old task is running, Tag Failed!"));
		return FALSE;
	}
	/*
	 * BUILD
	 */
	GstElement *filesrc=NULL;
	GstElement *demux=NULL;
	GstElement *mux=NULL;
	GstElement *parse=NULL;
	GstElement *filesink=NULL;
	GstElement *tagger=NULL;
	GstBus *bus=NULL;
	
	const gchar *codec=NULL;
	ly_mdh_put_pipeline=gst_pipeline_new("pipeline");
	filesrc=gst_element_factory_make("filesrc","filesrc");
	filesink=gst_element_factory_make("filesink","filesink");
	if(!ly_mdh_put_pipeline||!filesrc||!filesink)
	{
		if(ly_mdh_put_pipeline);
			gst_object_unref(ly_mdh_put_pipeline);
		g_mutex_unlock(ly_mdh_put_mutex);
		return FALSE;
	}
	
	//MP3
	if(strstr(md->codec,"MP3")!=NULL)
	{
		demux=gst_element_factory_make("id3demux","demux");
		tagger=gst_element_factory_make("id3v2mux","tagger");
		codec = "LAME";
		if(!demux||!tagger)
		{
			gst_object_unref(ly_mdh_put_pipeline);
			g_mutex_unlock(ly_mdh_put_mutex);
			return FALSE;
		}
	}
	//OGG
	else if(strstr(md->codec,"Vorbis")!=NULL)
	{
		tagger = gst_element_factory_make("vorbistag", "tagger");
		demux=gst_element_factory_make("oggdemux","demux");
		mux=gst_element_factory_make("oggmux","mux");
		parse = gst_element_factory_make("vorbisparse", "parse");
		codec = "Vorbis";
		if(!demux||!mux||!tagger||!parse)
		{
			gst_object_unref(ly_mdh_put_pipeline);
			g_mutex_unlock(ly_mdh_put_mutex);
			return FALSE;
		}
	}
	//FLAC
	else if(strstr(md->codec,"FLAC")!=NULL)
	{
		tagger = gst_element_factory_make("flactag", "tagger");
		codec="FLAC";
		if(!tagger)
		{
			gst_object_unref(ly_mdh_put_pipeline);
			g_mutex_unlock(ly_mdh_put_mutex);
			return FALSE;
		}
	}
	//APE
	else if(strstr(md->codec,"Monkey's Audio")!=NULL)
	{
		demux=gst_element_factory_make("apedemux","demux");
		tagger=gst_element_factory_make("apev2mux","tagger");
		codec="LAME";
		if(!demux||!tagger)
		{
			gst_object_unref(ly_mdh_put_pipeline);
			g_mutex_unlock(ly_mdh_put_mutex);
			return FALSE;
		}
	}
	else
	{
		gst_object_unref(ly_mdh_put_pipeline);
		g_mutex_unlock(ly_mdh_put_mutex);
		return FALSE;
	}

	/*
	 * SET
	 */
	gchar location_i[1024]="";
	gchar location_o[1024]="";
	g_snprintf(location_i, sizeof(location_i), "%s", md->uri+7);
	g_snprintf(location_o, sizeof(location_o), "%s%s-%s.audio", LY_GLA_TEMPDIR, md->artist, md->title);
	g_object_set(G_OBJECT(filesrc), "location", location_i, NULL);
	g_object_set(G_OBJECT(filesink), "location", location_o, NULL);

	gst_tag_setter_add_tags(GST_TAG_SETTER(tagger),
							GST_TAG_MERGE_REPLACE_ALL,
							GST_TAG_TITLE, md->title,
							GST_TAG_ARTIST, md->artist,
							GST_TAG_ALBUM, md->album,
							GST_TAG_GENRE, md->genre,
							GST_TAG_TRACK_NUMBER, md->track,
							GST_TAG_ENCODER, "Linnya",
							GST_TAG_ENCODER_VERSION, 1,
							GST_TAG_CODEC,codec,
							NULL);
	
	/*
	 *LINK
	 */
	//MP3
	if(strstr(md->codec,"MP3")!=NULL)
	{
		gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux,tagger,filesink, NULL);
		g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_id3_pad_cb), tagger);
		gst_element_link(filesrc, demux);
		gst_element_link(tagger, filesink);
	}
	//OGG
	else if(strstr(md->codec,"Vorbis")!=NULL)
	{
		gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux, tagger, parse, mux, filesink, NULL);
		g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_ogg_pad_cb), tagger);
		gst_element_link(filesrc, demux);
		gst_element_link_many(tagger, parse, mux, filesink,NULL);
	}
	//FLAC
	else if(strstr(md->codec,"FLAC")!=NULL)
	{
		gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, tagger, filesink, NULL);
		gst_element_link_many(filesrc, tagger, filesink, NULL);
	}
	//APE
	else if(strstr(md->codec,"Monkey's Audio")!=NULL)
	{
		gst_bin_add_many(GST_BIN(ly_mdh_put_pipeline), filesrc, demux,tagger,filesink, NULL);
		g_signal_connect(demux, "pad-added",G_CALLBACK(ly_mdh_push_add_id3_pad_cb), tagger);
		gst_element_link(filesrc, demux);
		gst_element_link(tagger, filesink);
	}
	else
	{
		gst_object_unref(ly_mdh_put_pipeline);
		g_mutex_unlock(ly_mdh_put_mutex);
		return FALSE;
	}
	
	bus = gst_pipeline_get_bus(GST_PIPELINE(ly_mdh_put_pipeline));
	gst_bus_add_watch(bus, (GstBusFunc)ly_mdh_push_handler_cb,  g_memdup(md,sizeof(LyMdhMetadata)));
	gst_object_unref(bus);
	gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_NULL);
	gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_READY);
	if(gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_PLAYING)==GST_STATE_CHANGE_FAILURE)
	{
		gst_element_set_state(ly_mdh_put_pipeline, GST_STATE_NULL);
		gst_object_unref(ly_mdh_put_pipeline);
		g_mutex_unlock(ly_mdh_put_mutex);
		return FALSE;
	}
	return TRUE;
}