4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include "mm_transcode.h"
22 #include "mm_transcode_internal.h"
25 mm_transcode_create(MMHandleType* MMHandle)
27 int ret = MM_ERROR_NONE;
28 handle_s *handle = NULL;
30 /* Check argument here */
31 if (MMHandle == NULL) {
32 debug_error ("Invalid arguments [tag null]\n");
33 return MM_ERROR_INVALID_ARGUMENT;
37 gst_init (NULL, NULL);
38 handle = g_new0 (handle_s, 1); /*handle = g_malloc(sizeof(handle_s));*/
40 debug_error("[ERROR] - handle");
41 return MM_ERROR_TRANSCODE_INTERNAL;
44 handle->decoder_vidp= g_new0 (handle_vidp_plugin_s, 1);
45 if (!handle->decoder_vidp) {
46 debug_error("[ERROR] - handle decoder video process bin");
47 return MM_ERROR_TRANSCODE_INTERNAL;
50 handle->decoder_audp= g_new0 (handle_audp_plugin_s, 1);
51 if (!handle->decoder_audp) {
52 debug_error("[ERROR] - handle decoder audio process bin");
53 return MM_ERROR_TRANSCODE_INTERNAL;
56 handle->encodebin= g_new0 (handle_encode_s, 1);
57 if (!handle->encodebin) {
58 debug_error("[ERROR] - handle encodebin");
59 return MM_ERROR_TRANSCODE_INTERNAL;
62 handle->property = g_new0 (handle_property_s, 1);
63 if (!handle->property) {
64 debug_error("[ERROR] - handle property");
65 return MM_ERROR_TRANSCODE_INTERNAL;
68 *MMHandle = (MMHandleType)handle;
71 debug_log("MMHandle: 0x%2x", handle);
72 handle->property->_MMHandle = 0;
74 debug_error("handle create Fail");
75 return MM_ERROR_TRANSCODE_INTERNAL;
82 mm_transcode_prepare (MMHandleType MMHandle, const char *in_Filename, mm_containerformat_e containerformat, mm_videoencoder_e videoencoder,
83 mm_audioencoder_e audioencoder)
85 int ret = MM_ERROR_NONE;
87 handle_s *handle = (handle_s *) MMHandle;
90 debug_error("[ERROR] - handle");
91 return MM_ERROR_INVALID_ARGUMENT;
94 if (!handle->property) {
95 debug_error("[ERROR] - handle property");
96 return MM_ERROR_TRANSCODE_INTERNAL;
99 if ((in_Filename == NULL) || (strlen (in_Filename) == 0)) {
100 debug_error("Invalid Input file");
101 return MM_ERROR_INVALID_ARGUMENT;
104 if (videoencoder == MM_VIDEOENCODER_NO_USE && audioencoder == MM_AUDIOENCODER_NO_USE) {
105 debug_error("No encoder resource");
106 return MM_ERROR_INVALID_ARGUMENT;
109 if (videoencoder == MM_VIDEOENCODER_H264) {
110 debug_error("Can't support encoding to H264");
111 return MM_ERROR_INVALID_ARGUMENT;
115 ret = _mm_transcode_set_handle_element(handle, in_Filename, containerformat, videoencoder, audioencoder);
116 if (ret != MM_ERROR_NONE) {
117 debug_error("ERROR -Set element");
121 debug_log("%s == %s", handle->property->sourcefile, in_Filename);
122 if (0 == strlen(handle->property->sourcefile) || 0 == strcmp(handle->property->sourcefile, in_Filename)) { /* protect the case of changing input file during transcoding */
124 ret = _mm_setup_pipeline(handle);
125 if (ret == MM_ERROR_NONE) {
126 debug_log("Success - Setup Pipeline");
128 debug_error("ERROR - Setup Pipeline");
132 /* video / auido stream */
133 ret = _mm_transcode_get_stream_info(handle);
134 if (ret == MM_ERROR_NONE) {
135 debug_log("Success - Get stream info");
137 debug_error("ERROR - Get stream info");
141 /* create pipeline */
142 ret = _mm_transcode_create(handle);
143 if (ret == MM_ERROR_NONE) {
144 debug_log("Success - Create Pipeline");
146 debug_error("ERROR -Create Pipeline");
151 ret = _mm_transcode_link(handle);
152 if (ret == MM_ERROR_NONE) {
153 debug_log("Success - Link pipeline");
155 debug_error("ERROR - Link pipeline");
160 ret = _mm_transcode_param_flush(handle);
161 if (ret == MM_ERROR_NONE) {
162 debug_log("Success - Init parameter");
164 debug_error("ERROR - Init parameter");
169 ret = _mm_transcode_thread(handle);
170 if (ret == MM_ERROR_NONE) {
171 debug_log("Success - Link pipeline");
173 debug_error("ERROR - Link pipeline");
177 /* Add_watcher Transcode Bus*/
178 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (handle->pipeline));
179 handle->property->bus_watcher = gst_bus_add_watch (bus, (GstBusFunc)_mm_cb_transcode_bus, handle);
180 gst_object_unref (GST_OBJECT(bus));
181 debug_log("Success - gst_object_unref (bus)");
184 handle->property->_MMHandle++;
190 mm_transcode (MMHandleType MMHandle, unsigned int resolution_width, unsigned int resolution_height, unsigned int fps_value, unsigned long start_position,
191 unsigned long duration, mm_seek_mode_e seek_mode, const char *out_Filename, mm_transcode_progress_callback progress_callback, mm_transcode_completed_callback completed_callback, void *user_param)
193 int ret = MM_ERROR_NONE;
194 handle_s *handle = (handle_s *) MMHandle;
197 debug_error("[ERROR] - handle");
198 return MM_ERROR_INVALID_ARGUMENT;
201 if (!handle->property) {
202 debug_error("[ERROR] - handle property");
203 return MM_ERROR_TRANSCODE_INTERNAL;
206 if (!completed_callback) {
207 debug_error("[ERROR] - completed_callback");
208 return MM_ERROR_INVALID_ARGUMENT;
212 debug_error("[ERROR] - out_Filename");
213 return MM_ERROR_INVALID_ARGUMENT;
216 if (duration < MIN_DURATION && duration !=0) {
217 debug_error("The minimum seek duration is 1000 msec ");
218 return MM_ERROR_INVALID_ARGUMENT;
221 handle->property->progress_cb= progress_callback;
222 handle->property->progress_cb_param = user_param;
223 debug_log("[MMHandle] 0x%2x [progress_cb] 0x%2x [progress_cb_param] 0x%2x", MMHandle, handle->property->progress_cb, handle->property->progress_cb_param);
225 handle->property->completed_cb = completed_callback;
226 handle->property->completed_cb_param = user_param;
227 debug_log("[MMHandle] 0x%2x [completed_cb] 0x%2x [completed_cb_param] 0x%2x", MMHandle, handle->property->completed_cb, handle->property->completed_cb_param);
229 if (!handle->property) {
230 debug_error("[ERROR] - handle property");
231 return MM_ERROR_TRANSCODE_INTERNAL;
234 if (handle->property->_MMHandle == 1) { /* check if prepare is called during transcoding */
235 handle_param_s *param = g_new0 (handle_param_s, 1);
237 /*g_value_init (param, G_TYPE_INT);*/
238 debug_log("[param] 0x%2x", param);
242 ret = _mm_transcode_set_handle_parameter(param, resolution_width, resolution_height, fps_value, start_position, duration, seek_mode, out_Filename);
243 if (ret != MM_ERROR_NONE) {
244 debug_error("ERROR -Set parameter");
248 ret = _mm_transcode_preset_capsfilter(handle, resolution_width, resolution_height);
249 if (ret == MM_ERROR_NONE) {
250 debug_log("Success - Preset Capsfilter");
252 debug_error("ERROR - Preset Capsfilter");
256 handle->property->is_busy = TRUE;
258 /*push data to handle */
259 g_async_queue_push (handle->property->queue, GINT_TO_POINTER(param));
266 mm_transcode_is_busy (MMHandleType MMHandle, bool *is_busy)
268 int ret = MM_ERROR_NONE;
270 handle_s *handle = (handle_s *) MMHandle;
273 debug_error("[ERROR] - handle");
274 return MM_ERROR_INVALID_ARGUMENT;
277 if (!handle->property) {
278 debug_error("[ERROR] - handle property");
279 return MM_ERROR_TRANSCODE_INTERNAL;
283 debug_error("[ERROR] - is_busy");
284 return MM_ERROR_INVALID_ARGUMENT;
287 *is_busy = handle->property->is_busy;
288 debug_log("[Transcoding....] %d", *is_busy);
294 mm_transcode_cancel (MMHandleType MMHandle)
296 int ret = MM_ERROR_NONE;
297 handle_s *handle = (handle_s *) MMHandle;
300 debug_error("[ERROR] - handle");
301 return MM_ERROR_INVALID_ARGUMENT;
304 if (!handle->property) {
305 debug_error("[ERROR] - handle property");
306 return MM_ERROR_TRANSCODE_INTERNAL;
309 if (handle->property->is_busy) {
310 debug_log("Cancel - [IS BUSY]");
311 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
312 if (ret != MM_ERROR_NONE) {
313 debug_error("ERROR - Null Pipeline");
317 if ((handle->param) && (strlen(handle->param->outputfile) > 0)) {
318 unlink(handle->param->outputfile);
319 debug_log("[Cancel] unlink %s", handle->param->outputfile);
321 debug_error("unlink error");
322 return MM_ERROR_TRANSCODE_INTERNAL;
324 g_mutex_lock (handle->property->thread_mutex);
325 g_cond_signal(handle->property->thread_cond);
326 debug_log("===> send completed signal <-cancel");
327 g_mutex_unlock (handle->property->thread_mutex);
330 handle->property->is_busy = FALSE;
336 mm_transcode_destroy (MMHandleType MMHandle)
338 int ret = MM_ERROR_NONE;
340 handle_s *handle = (handle_s*) MMHandle;
343 debug_error("[ERROR] - handle");
344 return MM_ERROR_INVALID_ARGUMENT;
347 if (!handle->property) {
348 debug_error("[ERROR] - handle property");
349 return MM_ERROR_TRANSCODE_INTERNAL;
352 g_mutex_lock(handle->property->thread_exit_mutex);
353 handle->property->repeat_thread_exit = TRUE;
354 if (handle->property->is_busy) {
355 ret = mm_transcode_cancel(MMHandle);
356 if (ret == MM_ERROR_NONE) {
357 debug_log("Success - Cancel Transcode");
359 debug_error("ERROR - Cancel Transcode");
363 /* handle->property->is_busy = FALSE; */
364 g_mutex_unlock(handle->property->thread_exit_mutex);
366 handle_param_s *param = g_new0 (handle_param_s, 1);
368 debug_log("[Try to Push Last Queue]");
369 g_async_queue_push (handle->property->queue, GINT_TO_POINTER(param));
371 debug_error("Fail to create Last Queue");
372 return MM_ERROR_INVALID_ARGUMENT;
375 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
376 if (ret != MM_ERROR_NONE) {
377 debug_error("ERROR - Null Pipeline");
380 debug_log("SUCCESS - Null Pipeline");
383 if ((handle->param) && (!handle->param->completed)) {
384 g_cond_signal(handle->property->thread_cond);
385 debug_log("===> send completed signal <-destroy");
386 g_mutex_unlock (handle->property->thread_mutex);
387 debug_log("unlock destory");
388 if (strlen(handle->param->outputfile) > 0) {
389 unlink(handle->param->outputfile);
390 debug_log("[Cancel] unlink %s", handle->param->outputfile);
394 ret = _mm_cleanup_pipeline(handle);
395 if (ret == MM_ERROR_NONE) {
396 debug_log("Success - CleanUp Pipeline");
398 debug_error("ERROR - CleanUp Pipeline");
401 TRANSCODE_FREE (param);
402 debug_log("[param] free");
408 mm_transcode_get_attrs(MMHandleType MMHandle, mm_containerformat_e *containerformat, mm_videoencoder_e *videoencoder,
409 mm_audioencoder_e *audioencoder, unsigned long *current_pos, unsigned long *duration, unsigned int *resolution_width, unsigned int *resolution_height)
412 int ret = MM_ERROR_NONE;
413 handle_s *handle = (handle_s *) MMHandle;
416 debug_error("[ERROR] - handle");
417 return MM_ERROR_INVALID_ARGUMENT;
420 if (!handle->property) {
421 debug_error("[ERROR] - handle property");
422 return MM_ERROR_TRANSCODE_INTERNAL;
425 if (!containerformat || !videoencoder ||!audioencoder || !current_pos || !duration || !resolution_width || !resolution_height) {
426 debug_error("[ERROR] - Invalid argument pointer");
427 return MM_ERROR_INVALID_ARGUMENT;
430 *containerformat = handle->property->containerformat;
431 *videoencoder = handle->property->videoencoder;
432 *audioencoder = handle->property->audioencoder;
434 if (!handle->property) {
435 debug_error("[ERROR] - handle property");
436 return MM_ERROR_TRANSCODE_INTERNAL;
439 if (handle->property->current_pos > handle->param->duration) {
440 *current_pos = handle->param->duration;
442 *current_pos = handle->property->current_pos;
444 *duration = handle->property->real_duration;
445 *resolution_width = handle->param->resolution_width;
446 *resolution_height = handle->param->resolution_height;
448 debug_log("containerformat : %d, videoencoder : %d, audioencoder : %d, current_pos : %d, duration : %d, resolution_width : %d, resolution_height : %d",
449 *containerformat, *videoencoder, *audioencoder, *current_pos, *duration, *resolution_width, *resolution_height);
455 mm_transcode_get_supported_container_format(mm_transcode_support_type_callback type_callback, void *user_param)
459 for (idx = 0; idx < MM_CONTAINER_NUM; idx++) {
460 if (type_callback(idx, user_param) == false)
462 debug_error("error occured. idx[%d]", idx);
467 return MM_ERROR_NONE;
471 mm_transcode_get_supported_video_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
475 for (idx = 0; idx < MM_VIDEOENCODER_H264; idx++) {
476 if (type_callback(idx, user_param) == false)
478 debug_error("error occured. idx[%d]", idx);
483 return MM_ERROR_NONE;
487 mm_transcode_get_supported_audio_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
491 for (idx = 0; idx < MM_AUDIOENCODER_NO_USE; idx++) {
492 if (type_callback(idx, user_param) == false)
494 debug_error("error occured. idx[%d]", idx);
499 return MM_ERROR_NONE;