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;
373 ret = _mm_cleanup_signal(handle);
374 if (ret == MM_ERROR_NONE) {
375 debug_log("Success - CleanUp Signal");
377 debug_error("ERROR - CleanUp Signal");
381 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
382 if (ret != MM_ERROR_NONE) {
383 debug_error("ERROR - Null Pipeline");
386 debug_log("SUCCESS - Null Pipeline");
389 if ((handle->param) && (!handle->param->completed)) {
390 g_cond_signal(handle->property->thread_cond);
391 debug_log("===> send completed signal <-destroy");
392 g_mutex_unlock(handle->property->thread_mutex);
393 debug_log("unlock destory");
394 if (strlen(handle->param->outputfile) > 0) {
395 unlink(handle->param->outputfile);
396 debug_log("[Cancel] unlink %s", handle->param->outputfile);
400 ret = _mm_cleanup_pipeline(handle);
401 if (ret == MM_ERROR_NONE) {
402 debug_log("Success - CleanUp Pipeline");
404 debug_error("ERROR - CleanUp Pipeline");
407 TRANSCODE_FREE(param);
408 debug_log("[param] free");
413 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)
416 int ret = MM_ERROR_NONE;
417 handle_s *handle = (handle_s *)MMHandle;
420 debug_error("[ERROR] - handle");
421 return MM_ERROR_INVALID_ARGUMENT;
424 if (!handle->property) {
425 debug_error("[ERROR] - handle property");
426 return MM_ERROR_TRANSCODE_INTERNAL;
429 if (!containerformat || !videoencoder || !audioencoder || !current_pos || !duration || !resolution_width || !resolution_height) {
430 debug_error("[ERROR] - Invalid argument pointer");
431 return MM_ERROR_INVALID_ARGUMENT;
434 *containerformat = handle->property->containerformat;
435 *videoencoder = handle->property->videoencoder;
436 *audioencoder = handle->property->audioencoder;
438 if (!handle->property) {
439 debug_error("[ERROR] - handle property");
440 return MM_ERROR_TRANSCODE_INTERNAL;
443 if (handle->property->current_pos > handle->param->duration)
444 *current_pos = handle->param->duration;
446 *current_pos = handle->property->current_pos;
447 *duration = handle->property->real_duration;
448 *resolution_width = handle->param->resolution_width;
449 *resolution_height = handle->param->resolution_height;
451 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);
456 int mm_transcode_get_supported_container_format(mm_transcode_support_type_callback type_callback, void *user_param)
460 for (idx = 0; idx < MM_CONTAINER_NUM; idx++) {
461 if (type_callback(idx, user_param) == false) {
462 debug_error("error occured. idx[%d]", idx);
467 return MM_ERROR_NONE;
470 int mm_transcode_get_supported_video_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
474 for (idx = 0; idx < MM_VIDEOENCODER_H264; idx++) {
475 if (type_callback(idx, user_param) == false) {
476 debug_error("error occured. idx[%d]", idx);
481 return MM_ERROR_NONE;
484 int mm_transcode_get_supported_audio_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
488 for (idx = 0; idx < MM_AUDIOENCODER_NO_USE; idx++) {
489 if (type_callback(idx, user_param) == false) {
490 debug_error("error occured. idx[%d]", idx);
495 return MM_ERROR_NONE;