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"
24 int mm_transcode_create(MMHandleType *MMHandle)
26 int ret = MM_ERROR_NONE;
27 handle_s *handle = NULL;
29 /* Check argument here */
30 if (MMHandle == NULL) {
31 debug_error("Invalid arguments [tag null]\n");
32 return MM_ERROR_INVALID_ARGUMENT;
37 /*handle = g_malloc(sizeof(handle_s)); */
38 handle = g_new0(handle_s, 1);
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");
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");
56 handle->encodebin = g_new0(handle_encode_s, 1);
57 if (!handle->encodebin) {
58 debug_error("[ERROR] - handle encodebin");
62 handle->property = g_new0(handle_property_s, 1);
63 if (!handle->property) {
64 debug_error("[ERROR] - handle property");
68 *MMHandle = (MMHandleType)handle;
70 debug_log("MMHandle: 0x%2x", handle);
71 handle->property->_MMHandle = 0;
76 TRANSCODE_FREE(handle->encodebin);
78 TRANSCODE_FREE(handle->decoder_audp);
80 TRANSCODE_FREE(handle->decoder_vidp);
82 TRANSCODE_FREE(handle);
83 return MM_ERROR_TRANSCODE_INTERNAL;
86 int mm_transcode_prepare(MMHandleType MMHandle, const char *in_Filename, mm_containerformat_e containerformat, mm_videoencoder_e videoencoder, mm_audioencoder_e audioencoder)
88 int ret = MM_ERROR_NONE;
90 handle_s *handle = (handle_s *) MMHandle;
93 debug_error("[ERROR] - handle");
94 return MM_ERROR_INVALID_ARGUMENT;
97 if (!handle->property) {
98 debug_error("[ERROR] - handle property");
99 return MM_ERROR_TRANSCODE_INTERNAL;
102 if ((in_Filename == NULL) || (strlen(in_Filename) == 0)) {
103 debug_error("Invalid Input file");
104 return MM_ERROR_INVALID_ARGUMENT;
107 if (videoencoder == MM_VIDEOENCODER_NO_USE && audioencoder == MM_AUDIOENCODER_NO_USE) {
108 debug_error("No encoder resource");
109 return MM_ERROR_INVALID_ARGUMENT;
112 if (videoencoder == MM_VIDEOENCODER_H264) {
113 debug_error("Can't support encoding to H264");
114 return MM_ERROR_INVALID_ARGUMENT;
118 ret = _mm_transcode_set_handle_element(handle, in_Filename, containerformat, videoencoder, audioencoder);
119 if (ret != MM_ERROR_NONE) {
120 debug_error("ERROR -Set element");
124 debug_log("%s == %s", handle->property->sourcefile, in_Filename);
125 /* protect the case of changing input file during transcoding */
126 if (0 == strlen(handle->property->sourcefile) || 0 == strcmp(handle->property->sourcefile, in_Filename)) {
128 ret = _mm_setup_pipeline(handle);
129 if (ret == MM_ERROR_NONE) {
130 debug_log("Success - Setup Pipeline");
132 debug_error("ERROR - Setup Pipeline");
136 /* video / auido stream */
137 ret = _mm_transcode_get_stream_info(handle);
138 if (ret == MM_ERROR_NONE) {
139 debug_log("Success - Get stream info");
141 debug_error("ERROR - Get stream info");
145 /* create pipeline */
146 ret = _mm_transcode_create(handle);
147 if (ret == MM_ERROR_NONE) {
148 debug_log("Success - Create Pipeline");
150 debug_error("ERROR -Create Pipeline");
155 ret = _mm_transcode_link(handle);
156 if (ret == MM_ERROR_NONE) {
157 debug_log("Success - Link pipeline");
159 debug_error("ERROR - Link pipeline");
164 ret = _mm_transcode_param_flush(handle);
165 if (ret == MM_ERROR_NONE) {
166 debug_log("Success - Init parameter");
168 debug_error("ERROR - Init parameter");
173 ret = _mm_transcode_thread(handle);
174 if (ret == MM_ERROR_NONE) {
175 debug_log("Success - Link pipeline");
177 debug_error("ERROR - Link pipeline");
181 /* Add_watcher Transcode Bus */
182 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(handle->pipeline));
183 handle->property->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)_mm_cb_transcode_bus, handle);
184 gst_object_unref(GST_OBJECT(bus));
185 debug_log("Success - gst_object_unref (bus)");
188 handle->property->_MMHandle++;
193 int mm_transcode(MMHandleType MMHandle, unsigned int resolution_width, unsigned int resolution_height, unsigned int fps_value, unsigned long start_position, 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)
195 int ret = MM_ERROR_NONE;
196 handle_s *handle = (handle_s *)MMHandle;
199 debug_error("[ERROR] - handle");
200 return MM_ERROR_INVALID_ARGUMENT;
203 if (!handle->property) {
204 debug_error("[ERROR] - handle property");
205 return MM_ERROR_TRANSCODE_INTERNAL;
208 if (!completed_callback) {
209 debug_error("[ERROR] - completed_callback");
210 return MM_ERROR_INVALID_ARGUMENT;
214 debug_error("[ERROR] - out_Filename");
215 return MM_ERROR_INVALID_ARGUMENT;
218 if (duration < MIN_DURATION && duration != 0) {
219 debug_error("The minimum seek duration is 1000 msec ");
220 return MM_ERROR_INVALID_ARGUMENT;
223 handle->property->progress_cb = progress_callback;
224 handle->property->progress_cb_param = user_param;
225 debug_log("[MMHandle] 0x%2x [progress_cb] 0x%2x [progress_cb_param] 0x%2x", MMHandle, handle->property->progress_cb, handle->property->progress_cb_param);
227 handle->property->completed_cb = completed_callback;
228 handle->property->completed_cb_param = user_param;
229 debug_log("[MMHandle] 0x%2x [completed_cb] 0x%2x [completed_cb_param] 0x%2x", MMHandle, handle->property->completed_cb, handle->property->completed_cb_param);
231 if (!handle->property) {
232 debug_error("[ERROR] - handle property");
233 return MM_ERROR_TRANSCODE_INTERNAL;
235 /* check if prepare is called during transcoding */
236 if (handle->property->_MMHandle == 1) {
237 handle_param_s *param = g_new0(handle_param_s, 1);
239 /*g_value_init (param, G_TYPE_INT); */
240 debug_log("[param] 0x%2x", param);
244 ret = _mm_transcode_set_handle_parameter(param, resolution_width, resolution_height, fps_value, start_position, duration, seek_mode, out_Filename);
245 if (ret != MM_ERROR_NONE) {
246 debug_error("ERROR -Set parameter");
250 ret = _mm_transcode_preset_capsfilter(handle, resolution_width, resolution_height);
251 if (ret == MM_ERROR_NONE) {
252 debug_log("Success - Preset Capsfilter");
254 debug_error("ERROR - Preset Capsfilter");
258 handle->property->is_busy = TRUE;
260 /*push data to handle */
261 g_async_queue_push(handle->property->queue, GINT_TO_POINTER(param));
267 int mm_transcode_is_busy(MMHandleType MMHandle, bool *is_busy)
269 int ret = MM_ERROR_NONE;
271 handle_s *handle = (handle_s *)MMHandle;
274 debug_error("[ERROR] - handle");
275 return MM_ERROR_INVALID_ARGUMENT;
278 if (!handle->property) {
279 debug_error("[ERROR] - handle property");
280 return MM_ERROR_TRANSCODE_INTERNAL;
284 debug_error("[ERROR] - is_busy");
285 return MM_ERROR_INVALID_ARGUMENT;
288 *is_busy = handle->property->is_busy;
289 debug_log("[Transcoding....] %d", *is_busy);
294 int 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;
335 int mm_transcode_destroy(MMHandleType MMHandle)
337 int ret = MM_ERROR_NONE;
339 handle_s *handle = (handle_s *)MMHandle;
342 debug_error("[ERROR] - handle");
343 return MM_ERROR_INVALID_ARGUMENT;
346 if (!handle->property) {
347 debug_error("[ERROR] - handle property");
348 return MM_ERROR_TRANSCODE_INTERNAL;
351 g_mutex_lock(handle->property->thread_exit_mutex);
352 handle->property->repeat_thread_exit = TRUE;
353 if (handle->property->is_busy) {
354 ret = mm_transcode_cancel(MMHandle);
355 if (ret == MM_ERROR_NONE) {
356 debug_log("Success - Cancel Transcode");
358 debug_error("ERROR - Cancel Transcode");
362 /* handle->property->is_busy = FALSE; */
363 g_mutex_unlock(handle->property->thread_exit_mutex);
365 handle_param_s *param = g_new0(handle_param_s, 1);
367 debug_log("[Try to Push Last Queue]");
368 g_async_queue_push(handle->property->queue, GINT_TO_POINTER(param));
370 debug_error("Fail to create Last Queue");
371 return MM_ERROR_INVALID_ARGUMENT;
374 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
375 if (ret != MM_ERROR_NONE) {
376 debug_error("ERROR - Null Pipeline");
379 debug_log("SUCCESS - Null Pipeline");
382 if ((handle->param) && (!handle->param->completed)) {
383 g_cond_signal(handle->property->thread_cond);
384 debug_log("===> send completed signal <-destroy");
385 g_mutex_unlock(handle->property->thread_mutex);
386 debug_log("unlock destory");
387 if (strlen(handle->param->outputfile) > 0) {
388 unlink(handle->param->outputfile);
389 debug_log("[Cancel] unlink %s", handle->param->outputfile);
393 ret = _mm_cleanup_pipeline(handle);
394 if (ret == MM_ERROR_NONE) {
395 debug_log("Success - CleanUp Pipeline");
397 debug_error("ERROR - CleanUp Pipeline");
400 TRANSCODE_FREE(param);
401 debug_log("[param] free");
406 int mm_transcode_get_attrs(MMHandleType MMHandle, mm_containerformat_e * containerformat, mm_videoencoder_e * videoencoder, mm_audioencoder_e * audioencoder, unsigned long *current_pos, unsigned long *duration, unsigned int *resolution_width, unsigned int *resolution_height)
409 int ret = MM_ERROR_NONE;
410 handle_s *handle = (handle_s *)MMHandle;
413 debug_error("[ERROR] - handle");
414 return MM_ERROR_INVALID_ARGUMENT;
417 if (!handle->property) {
418 debug_error("[ERROR] - handle property");
419 return MM_ERROR_TRANSCODE_INTERNAL;
422 if (!containerformat || !videoencoder || !audioencoder || !current_pos || !duration || !resolution_width || !resolution_height) {
423 debug_error("[ERROR] - Invalid argument pointer");
424 return MM_ERROR_INVALID_ARGUMENT;
427 *containerformat = handle->property->containerformat;
428 *videoencoder = handle->property->videoencoder;
429 *audioencoder = handle->property->audioencoder;
431 if (!handle->property) {
432 debug_error("[ERROR] - handle property");
433 return MM_ERROR_TRANSCODE_INTERNAL;
436 if (handle->property->current_pos > handle->param->duration)
437 *current_pos = handle->param->duration;
439 *current_pos = handle->property->current_pos;
440 *duration = handle->property->real_duration;
441 *resolution_width = handle->param->resolution_width;
442 *resolution_height = handle->param->resolution_height;
444 debug_log("containerformat : %d, videoencoder : %d, audioencoder : %d, current_pos : %d, duration : %d, resolution_width : %d, resolution_height : %d", *containerformat, *videoencoder, *audioencoder, *current_pos, *duration, *resolution_width, *resolution_height);
449 int mm_transcode_get_supported_container_format(mm_transcode_support_type_callback type_callback, void *user_param)
453 for (idx = 0; idx < MM_CONTAINER_NUM; idx++) {
454 if (type_callback(idx, user_param) == false) {
455 debug_error("error occured. idx[%d]", idx);
460 return MM_ERROR_NONE;
463 int mm_transcode_get_supported_video_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
467 for (idx = 0; idx < MM_VIDEOENCODER_H264; idx++) {
468 if (type_callback(idx, user_param) == false) {
469 debug_error("error occured. idx[%d]", idx);
474 return MM_ERROR_NONE;
477 int mm_transcode_get_supported_audio_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
481 for (idx = 0; idx < MM_AUDIOENCODER_NO_USE; idx++) {
482 if (type_callback(idx, user_param) == false) {
483 debug_error("error occured. idx[%d]", idx);
488 return MM_ERROR_NONE;