// // Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas@softcatala.org // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // #include "mistelix.h" typedef struct { const char *media; const char *plugin; const char *pipeline; } supported_media; void run_pipeline (GstElement * pipe); supported_media supported_medias[] = { // // AC3 (ffenc_ac3) is the most common audio encoding for DVD. We may want to consider to switch // to AC3 when the dvd_mux supports for it becomes widely available. See http://bugzilla.gnome.org/show_bug.cgi?id=588546 // {"video/mpeg", "ffenc_mpeg2video", "filesrc location=\"%s\" ! mpegdemux name=demux \\ " "{ffmux_dvd preload=500000 maxdelay=699999 name=mux ! filesink location=\"%s\" } \\ " "{demux.audio_00 ! queue ! flump3dec ! queue ! audioresample ! audio/x-raw-int, rate=48000 ! ffenc_mp2 ! mux. } \\ " "{demux.video_00 ! queue ! mpeg2dec ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,format=(fourcc)I420,framerate=%u/1 ! queue ! ffenc_mpeg2video ! mux. }"}, {"video/x-msvideo", "avidemux", "filesrc location=\"%s\" ! decodebin name=demux \\ " "{ffmux_dvd preload=500000 maxdelay=699999 name=mux ! filesink location=\"%s\" } \\ " "{demux. ! queue ! audioresample ! audio/x-raw-int, rate=48000 ! ffenc_mp2 ! mux. } \\ " "{demux. ! queue ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,format=(fourcc)I420,framerate=%u/1 ! queue ! ffenc_mpeg2video ! mux. }"}, {"video/x-ms-asf", "asfdemux", "filesrc location=\"%s\" ! decodebin name=demux \\ " "{ffmux_dvd preload=500000 maxdelay=699999 name=mux ! filesink location=\"%s\" } \\ " "{demux. ! queue ! audioresample ! audio/x-raw-int, rate=48000 ! ffenc_mp2 ! mux. } \\ " "{demux. ! queue ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,format=(fourcc)I420,framerate=%u/1 ! queue ! ffenc_mpeg2video ! mux. }"}, {"application/ogg", "oggdemux", "filesrc location=\"%s\" ! oggdemux name=demux \\ " "{ffmux_dvd preload=500000 maxdelay=699999 name=mux ! filesink location=\"%s\" } \\ " "{demux. !queue ! vorbisdec ! queue ! audioconvert ! audioresample ! audio/x-raw-int, rate=48000 ! ffenc_mp2 ! mux. } \\ " "{demux. ! queue ! theoradec ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,format=(fourcc)I420,framerate=%u/1 ! queue ! ffenc_mpeg2video ! mux. }"}, }; void mistelix_video_extensions (char* extensions) { strcpy (extensions, "*.mpeg; *.mpg; *.avi; *.wmv; *.asf;*.ogg"); } int mistelix_video_supported (const char* file, char* msg) { char media [2048]; int i, ncodecs, c, media_present, plugin_present; char* pos; //#ifdef _DEBUG printf ("*** mistelix_video_supported %s\n", file); //#endif mistelix_detect_media (file, media); pos = strchr (media, ','); if (pos != NULL) *pos = 0x0; if (*media == 0x0) return 1; // Could not identify media ncodecs = mistelix_get_plugins_count (); char *codecs[ncodecs]; mistelix_get_plugins (codecs); media_present = plugin_present = 0; for (i = 0; i < sizeof (supported_medias) / sizeof (supported_media); i++) { //printf ("Comparing %s with %s\n", media, supported_medias[i].media); if (strcmp (media, supported_medias[i].media) != 0) continue; media_present = 1; for (c = 0; c < ncodecs; c++) { //printf ("Comparing %s with %s\n", supported_medias[i].plugin, codecs[c]); if (strcmp (supported_medias[i].plugin, codecs[c]) == 0) { plugin_present = 1; break; } } break; } for (c = 0; c < ncodecs; c++) free (codecs [c]); if (media_present == 0) return 2; // Format not supported if (media_present == 1 && plugin_present == 0) { strcpy (msg, supported_medias[i].plugin); return 3; // Supported media but codec not found + codec name } return 0; // Supported media & codec found } int mistelix_video_convert (const char* filein, const char* fileout, unsigned int frames_sec) { char media [2048]; int i, ncodecs, c, media_present, plugin_present; char* pos; mistelix_detect_media (filein, media); #ifdef _DEBUG printf ("*** mistelix_convert_media %s %s\n", filein, fileout); #endif pos = strchr (media, ','); if (pos != NULL) *pos = 0x0; if (*media == 0x0) return 1; // Could not identify media ncodecs = mistelix_get_plugins_count (); char *codecs[ncodecs]; mistelix_get_plugins (codecs); media_present = plugin_present = 0; for (i = 0; i < sizeof (supported_medias) / sizeof (supported_media); i++) { if (strcmp (media, supported_medias[i].media) != 0) continue; media_present = 1; for (c = 0; c < ncodecs; c++) { if (strcmp (supported_medias[i].plugin, codecs[c]) == 0) { plugin_present = 1; break; } } break; } for (c = 0; c < ncodecs; c++) free (codecs [c]); if (media_present == 0) return 2; // Format not supported if (media_present == 1 && plugin_present == 0) return 3; // Supported media but codec not found + codec name char desc [1024]; GstElement *pipe; mistelix_check_init (); sprintf (desc, supported_medias[i].pipeline, filein, fileout, frames_sec); printf ("pipe %s\n", desc); pipe = gst_parse_launch (desc, NULL); run_pipeline (pipe); return 0; } /* Private functions */ /* Runs standard pipline that ends by an EOS event */ void run_pipeline (GstElement * pipe) { GstBus *bus; GstMessage *message; GstMessageType revent; GstStateChangeReturn ret; #ifdef _DEBUG printf ("*** run_pipeline start\n"); #endif g_assert (pipe); bus = gst_element_get_bus (pipe); g_assert (bus); gst_element_set_state (pipe, GST_STATE_PLAYING); /* Wait for status change */ gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE); /* We get a GST_MESSAGE_EOS when the pipe is finished */ while (1) { message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2); if (message) { revent = GST_MESSAGE_TYPE (message); #ifdef _DEBUG printf ("*** run_pipeline message: %s (%x)\n", gst_message_type_get_name (revent), revent); #endif gst_message_unref (message); } else revent = GST_MESSAGE_UNKNOWN; if (revent == GST_MESSAGE_ERROR) { #ifdef _DEBUG printf ("*** run_pipeline exiting reason GST_MESSAGE_ERROR\n"); #endif break; } if (revent == GST_MESSAGE_EOS) { #ifdef _DEBUG printf ("*** run_pipeline exiting reason: GST_MESSAGE_EOS\n"); #endif break; } } gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE); //gst_object_unref (pipe); gst_bus_set_flushing (bus, TRUE); //gst_object_unref (bus); #ifdef _DEBUG printf ("*** run_pipeline end\n"); #endif }