need help transcoding audio only files

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

need help transcoding audio only files

Peter Quiring
I'm having some success with GStreamer but having some difficulties with audio only files.

If I transcode WMV to OGG it works.
But if I try to transcode MP3 to WAV it fails.

ERROR : encodebin says : Couldn't create encoder for format audio/x-wav
In my encoding profile I don't use a container, only an audio profile that is set to the encodebin "profile" property.

And if I try and just decode MP3 to RAW it never starts and my appsink blocks forever.  I don't see any WARN or ERRORs in this case.  But my decoder works with WMV files fine.

The gstreamer0.10-ffmpeg package is installed (ubuntu).

Here is my transcoder source (it's Java Native code).
I could post my decoder to RAW source if desired but it's basically half of the transcoder but goes to an appsink instead of an encodebin/filesink.

The call I make to transcode MP3 to WAV is:

JNI.gst_transcoder(id, mp3filein, wavfileout, null, "audio/x-wav", null, true);
//args = instance ID, fileinString,fileoutString, containerCodec, audioCodec, videoCodec, startPlayingBoolean

//the instance ID is just an index into an array of structs holding info related to GStreamer

struct insts {
  //instance vars
  GstElement *pipeline, *videosink, *appsink_audio, *appsink_video, *filesrc, *filesink
    , *decoder, *encoder, *appsrc_audio, *appsrc_video, *alphacolor, *imgenc, *imgdec
    , *alsasrc, *alsasink, *audioresample, *audioconvert;
  GstCaps *caps_audio, *caps_video;
  int wav_size;
  guint8 *wav_data;
  jmethodID method;
  jclass cls;
  jobject obj;
  int id;
  JavaVM *vm;
};

#define instcnt 32

struct insts inst[instcnt];

static void
cb_newpad_transcoder (GstElement *bin,
           GstPad     *pad,
           gpointer    data)
{
  GstCaps *caps;
  GstStructure *str;
  GstPad *audiopad, *videopad;
  struct insts *inst = (struct insts*)data;

  /* check media type */
  caps = gst_pad_get_caps(pad);
  str = gst_caps_get_structure(caps, 0);
  if (g_strrstr(gst_structure_get_name(str), "audio")) {
    /* only link once */
    audiopad = gst_element_get_request_pad(inst->encoder, "audio_%d");
    if (GST_PAD_IS_LINKED (audiopad)) {
      printf("pad already linked");
      g_object_unref(audiopad);
      return;
    }
    gst_caps_unref(caps);
    gst_pad_link(pad, audiopad);
    return;
  }
  if (g_strrstr(gst_structure_get_name(str), "video")) {
    /* only link once */
    videopad = gst_element_get_request_pad(inst->encoder, "video_%d");
    if (GST_PAD_IS_LINKED (videopad)) {
      printf("pad already linked");
      g_object_unref(videopad);
      return;
    }
    gst_caps_unref(caps);
    gst_pad_link(pad, videopad);
    return;
  }
  printf("unknown pad type:%s\n", gst_structure_get_name(str));
  gst_caps_unref(caps);
}

//gst transcoder
JNIEXPORT jboolean JNICALL Java_javaforce_jni_JNI_gst_1transcoder
  (JNIEnv *env, jclass cls, jint id, jstring _filein, jstring _fileout, jstring _container, jstring _acodec, jstring _vcodec, jboolean start_coding)
{
  GstBus *bus;

  inst[id].pipeline = gst_pipeline_new("my-pipeline");
  inst[id].filesrc = gst_element_factory_make("filesrc", "my-filesrc");
  inst[id].filesink = gst_element_factory_make("filesink", "my-filesink");
  inst[id].decoder = gst_element_factory_make("decodebin2", "my-decoder");
  inst[id].encoder = gst_element_factory_make("encodebin", "my-encoder");

  g_signal_connect(inst[id].decoder, "pad-added", G_CALLBACK(cb_newpad_transcoder), &inst[id]);

  gst_bin_add_many(GST_BIN(inst[id].pipeline), inst[id].filesrc, inst[id].decoder
    , inst[id].filesink, inst[id].encoder
    , NULL);

  //create EncoderProfiles and assign to encoder
  GstEncodingContainerProfile *cprof = NULL;
  GstEncodingAudioProfile *aprof = NULL;
  GstEncodingVideoProfile *vprof = NULL;
  GstCaps *caps;

  if (_container != NULL) {
    const char *container = (*env)->GetStringUTFChars(env,_container,NULL);
    caps = gst_caps_from_string(container);
    cprof = gst_encoding_container_profile_new(NULL, NULL, caps, NULL);
    gst_caps_unref(caps);
    (*env)->ReleaseStringUTFChars(env, _container, container);
  }

  if (_acodec != NULL) {
    const char *acodec = (*env)->GetStringUTFChars(env,_acodec,NULL);
    caps = gst_caps_from_string(acodec);
    aprof = (GstEncodingAudioProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0);
    if (cprof != NULL) gst_encoding_container_profile_add_profile(cprof, (GstEncodingProfile*)aprof);
    gst_caps_unref(caps);
    (*env)->ReleaseStringUTFChars(env, _acodec, acodec);
  }

  if (_vcodec != NULL) {
    const char *vcodec = (*env)->GetStringUTFChars(env,_vcodec,NULL);
    caps = gst_caps_from_string(vcodec);
    vprof = (GstEncodingVideoProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0);
    if (cprof != NULL) gst_encoding_container_profile_add_profile(cprof, (GstEncodingProfile*)vprof);
    gst_caps_unref(caps);
    (*env)->ReleaseStringUTFChars(env, _vcodec, vcodec);
  }

  if (cprof != NULL) {
    g_object_set (G_OBJECT (inst[id].encoder), "profile", cprof, NULL);
  } else if (aprof != NULL) {
    g_object_set (G_OBJECT (inst[id].encoder), "profile", aprof, NULL);
  } else if (vprof != NULL) {
    g_object_set (G_OBJECT (inst[id].encoder), "profile", vprof, NULL);
  }

//this crashes???
//  if (cprof != NULL) gst_encoding_profile_unref(cprof);
//  if (aprof != NULL) gst_encoding_profile_unref(aprof);
//  if (vprof != NULL) gst_encoding_profile_unref(vprof);

  gst_element_link(inst[id].filesrc, inst[id].decoder);
  gst_element_link(inst[id].encoder, inst[id].filesink);

  const char *filein = (*env)->GetStringUTFChars(env,_filein,NULL);
  if (filein) g_object_set(G_OBJECT(inst[id].filesrc), "location", filein, NULL);
  (*env)->ReleaseStringUTFChars(env, _filein, filein);

  const char *fileout = (*env)->GetStringUTFChars(env,_fileout,NULL);
  if (fileout) g_object_set(G_OBJECT(inst[id].filesink), "location", fileout, NULL);
  (*env)->ReleaseStringUTFChars(env, _fileout, fileout);

  bus = gst_pipeline_get_bus(GST_PIPELINE(inst[id].pipeline));
  gst_bus_add_watch(bus, bus_call, &inst[id]);
  gst_object_unref(bus);

  if (start_coding) gst_element_set_state(GST_ELEMENT(inst[id].pipeline), GST_STATE_PLAYING);

  return TRUE;
}

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: need help transcoding audio only files

Tim-Philipp Müller-2
On Thu, 2012-06-28 at 09:25 -0700, Peter Quiring wrote:

Hi Peter,

> If I transcode WMV to OGG it works.
> But if I try to transcode MP3 to WAV it fails.
>
> ERROR : encodebin says : Couldn't create encoder for format audio/x-wav
> In my encoding profile I don't use a container, only an audio profile that

Have you tried specifying audio/x-wav as container profile?

Despite the name, wavenc is categorised as a muxer according to
gst-inspect-0.10 wavenc:

Factory Details:
  Long name: WAV audio muxer
  Class: Codec/Muxer/Audio
  ...
Plugin Details:
  Name: wavenc
  Description: Encode raw audio into WAV
 

Cheers
 -Tim

_______________________________________________
gstreamer-devel mailing list
[hidden email]
http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: need help transcoding audio only files

Peter Quiring
I got it now.

container = "audio/x-wav"
audioCodec = "audio/x-raw-int"

I had tried "audio/x-wav" for both container and audioCodec which didn't work either.
Didn't think of "audio/x-raw-int" for the audioCodec.

Thanks again.