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 LOGE("Invalid arguments [tag null]");
32 return MM_ERROR_INVALID_ARGUMENT;
37 /*handle = g_malloc(sizeof(handle_s)); */
38 handle = g_new0(handle_s, 1);
40 LOGE("[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 LOGE("[ERROR] - handle decoder video process bin");
50 handle->decoder_audp = g_new0(handle_audp_plugin_s, 1);
51 if (!handle->decoder_audp) {
52 LOGE("[ERROR] - handle decoder audio process bin");
56 handle->encodebin = g_new0(handle_encode_s, 1);
57 if (!handle->encodebin) {
58 LOGE("[ERROR] - handle encodebin");
62 handle->property = g_new0(handle_property_s, 1);
63 if (!handle->property) {
64 LOGE("[ERROR] - handle property");
68 *MMHandle = (MMHandleType)handle;
70 LOGD("MMHandle: %p", 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 LOGE("[ERROR] - handle");
94 return MM_ERROR_INVALID_ARGUMENT;
97 if (!handle->property) {
98 LOGE("[ERROR] - handle property");
99 return MM_ERROR_TRANSCODE_INTERNAL;
102 if ((in_Filename == NULL) || (strlen(in_Filename) == 0)) {
103 LOGE("Invalid Input file");
104 return MM_ERROR_INVALID_ARGUMENT;
107 if (videoencoder == MM_VIDEOENCODER_NO_USE && audioencoder == MM_AUDIOENCODER_NO_USE) {
108 LOGE("No encoder resource");
109 return MM_ERROR_INVALID_ARGUMENT;
112 if (videoencoder == MM_VIDEOENCODER_H264) {
113 LOGE("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 LOGE("ERROR -Set element");
124 LOGD("%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 LOGD("Success - Setup Pipeline");
132 LOGE("ERROR - Setup Pipeline");
136 /* video / auido stream */
137 ret = _mm_transcode_get_stream_info(handle);
138 if (ret == MM_ERROR_NONE) {
139 LOGD("Success - Get stream info");
141 LOGE("ERROR - Get stream info");
145 /* create pipeline */
146 ret = _mm_transcode_create(handle);
147 if (ret == MM_ERROR_NONE) {
148 LOGD("Success - Create Pipeline");
150 LOGE("ERROR -Create Pipeline");
155 ret = _mm_transcode_link(handle);
156 if (ret == MM_ERROR_NONE) {
157 LOGD("Success - Link pipeline");
159 LOGE("ERROR - Link pipeline");
164 ret = _mm_transcode_param_flush(handle);
165 if (ret == MM_ERROR_NONE) {
166 LOGD("Success - Init parameter");
168 LOGE("ERROR - Init parameter");
173 ret = _mm_transcode_thread(handle);
174 if (ret == MM_ERROR_NONE) {
175 LOGD("Success - Link pipeline");
177 LOGE("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 LOGD("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 LOGE("[ERROR] - handle");
200 return MM_ERROR_INVALID_ARGUMENT;
203 if (!handle->property) {
204 LOGE("[ERROR] - handle property");
205 return MM_ERROR_TRANSCODE_INTERNAL;
208 if (!completed_callback) {
209 LOGE("[ERROR] - completed_callback");
210 return MM_ERROR_INVALID_ARGUMENT;
214 LOGE("[ERROR] - out_Filename");
215 return MM_ERROR_INVALID_ARGUMENT;
218 if (duration < MIN_DURATION && duration != 0) {
219 LOGE("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 LOGD("[MMHandle] %p [progress_cb] %p [progress_cb_param] %p",
226 MMHandle, handle->property->progress_cb, handle->property->progress_cb_param);
228 handle->property->completed_cb = completed_callback;
229 handle->property->completed_cb_param = user_param;
230 LOGD("[MMHandle] %p [completed_cb] %p [completed_cb_param] %p",
231 MMHandle, handle->property->completed_cb, handle->property->completed_cb_param);
233 if (!handle->property) {
234 LOGE("[ERROR] - handle property");
235 return MM_ERROR_TRANSCODE_INTERNAL;
237 /* check if prepare is called during transcoding */
238 if (handle->property->_MMHandle == 1) {
239 handle_param_s *param = g_new0(handle_param_s, 1);
241 /*g_value_init (param, G_TYPE_INT); */
242 LOGD("[param] %p", param);
246 ret = _mm_transcode_set_handle_parameter(param, resolution_width, resolution_height, fps_value, start_position, duration, seek_mode, out_Filename);
247 if (ret != MM_ERROR_NONE) {
248 LOGE("ERROR -Set parameter");
249 TRANSCODE_FREE(param);
253 ret = _mm_transcode_preset_capsfilter(handle, resolution_width, resolution_height);
254 if (ret == MM_ERROR_NONE) {
255 LOGD("Success - Preset Capsfilter");
257 LOGE("ERROR - Preset Capsfilter");
258 TRANSCODE_FREE(param);
262 handle->property->is_busy = TRUE;
264 /*push data to handle */
265 g_async_queue_push(handle->property->queue, GINT_TO_POINTER(param));
271 int mm_transcode_is_busy(MMHandleType MMHandle, bool *is_busy)
273 int ret = MM_ERROR_NONE;
275 handle_s *handle = (handle_s *)MMHandle;
278 LOGE("[ERROR] - handle");
279 return MM_ERROR_INVALID_ARGUMENT;
282 if (!handle->property) {
283 LOGE("[ERROR] - handle property");
284 return MM_ERROR_TRANSCODE_INTERNAL;
288 LOGE("[ERROR] - is_busy");
289 return MM_ERROR_INVALID_ARGUMENT;
292 *is_busy = handle->property->is_busy;
293 LOGD("[Transcoding....] %d", *is_busy);
298 int mm_transcode_cancel(MMHandleType MMHandle)
300 int ret = MM_ERROR_NONE;
301 handle_s *handle = (handle_s *)MMHandle;
304 LOGE("[ERROR] - handle");
305 return MM_ERROR_INVALID_ARGUMENT;
308 if (!handle->property) {
309 LOGE("[ERROR] - handle property");
310 return MM_ERROR_TRANSCODE_INTERNAL;
313 if (handle->property->is_busy) {
314 LOGD("Cancel - [IS BUSY]");
315 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
316 if (ret != MM_ERROR_NONE) {
317 LOGE("ERROR - Null Pipeline");
321 if ((handle->param) && (strlen(handle->param->outputfile) > 0)) {
322 unlink(handle->param->outputfile);
323 LOGD("[Cancel] unlink %s", handle->param->outputfile);
325 LOGE("unlink error");
326 return MM_ERROR_TRANSCODE_INTERNAL;
328 g_mutex_lock(handle->property->thread_mutex);
329 g_cond_signal(handle->property->thread_cond);
330 LOGD("===> send completed signal <-cancel");
331 g_mutex_unlock(handle->property->thread_mutex);
334 handle->property->is_busy = FALSE;
339 int mm_transcode_destroy(MMHandleType MMHandle)
341 int ret = MM_ERROR_NONE;
343 handle_s *handle = (handle_s *)MMHandle;
346 LOGE("[ERROR] - handle");
347 return MM_ERROR_INVALID_ARGUMENT;
350 if (!handle->property) {
351 LOGE("[ERROR] - handle property");
352 return MM_ERROR_TRANSCODE_INTERNAL;
355 g_mutex_lock(handle->property->thread_exit_mutex);
356 handle->property->repeat_thread_exit = TRUE;
357 if (handle->property->is_busy) {
358 ret = mm_transcode_cancel(MMHandle);
359 if (ret == MM_ERROR_NONE) {
360 LOGD("Success - Cancel Transcode");
362 LOGE("ERROR - Cancel Transcode");
366 /* handle->property->is_busy = FALSE; */
367 g_mutex_unlock(handle->property->thread_exit_mutex);
369 handle_param_s *param = g_new0(handle_param_s, 1);
371 LOGD("[Try to Push Last Queue]");
372 g_async_queue_push(handle->property->queue, GINT_TO_POINTER(param));
374 LOGE("Fail to create Last Queue");
375 return MM_ERROR_INVALID_ARGUMENT;
377 ret = _mm_cleanup_signal(handle);
378 if (ret == MM_ERROR_NONE) {
379 LOGD("Success - CleanUp Signal");
381 LOGE("ERROR - CleanUp Signal");
385 ret = _mm_transcode_state_change(handle, GST_STATE_NULL);
386 if (ret != MM_ERROR_NONE) {
387 LOGE("ERROR - Null Pipeline");
390 LOGD("SUCCESS - Null Pipeline");
393 if ((handle->param) && (!handle->param->completed)) {
394 g_cond_signal(handle->property->thread_cond);
395 LOGD("===> send completed signal <-destroy");
396 g_mutex_unlock(handle->property->thread_mutex);
397 LOGD("unlock destory");
398 if (strlen(handle->param->outputfile) > 0) {
399 unlink(handle->param->outputfile);
400 LOGD("[Cancel] unlink %s", handle->param->outputfile);
404 ret = _mm_cleanup_pipeline(handle);
405 if (ret == MM_ERROR_NONE) {
406 LOGD("Success - CleanUp Pipeline");
408 LOGE("ERROR - CleanUp Pipeline");
411 TRANSCODE_FREE(param);
412 LOGD("[param] free");
417 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)
420 int ret = MM_ERROR_NONE;
421 handle_s *handle = (handle_s *)MMHandle;
424 LOGE("[ERROR] - handle");
425 return MM_ERROR_INVALID_ARGUMENT;
428 if (!handle->property) {
429 LOGE("[ERROR] - handle property");
430 return MM_ERROR_TRANSCODE_INTERNAL;
433 if (!containerformat || !videoencoder || !audioencoder || !current_pos || !duration || !resolution_width || !resolution_height) {
434 LOGE("[ERROR] - Invalid argument pointer");
435 return MM_ERROR_INVALID_ARGUMENT;
438 *containerformat = handle->property->containerformat;
439 *videoencoder = handle->property->videoencoder;
440 *audioencoder = handle->property->audioencoder;
442 if (!handle->property) {
443 LOGE("[ERROR] - handle property");
444 return MM_ERROR_TRANSCODE_INTERNAL;
447 if (handle->property->current_pos > handle->param->duration)
448 *current_pos = handle->param->duration;
450 *current_pos = handle->property->current_pos;
451 *duration = handle->property->real_duration;
452 *resolution_width = handle->param->resolution_width;
453 *resolution_height = handle->param->resolution_height;
455 LOGD("containerformat : %d, videoencoder : %d, audioencoder : %d, current_pos : %lu, duration : %lu, resolution_width : %d, resolution_height : %d",
456 *containerformat, *videoencoder, *audioencoder, *current_pos,
457 *duration, *resolution_width, *resolution_height);
462 int mm_transcode_get_supported_container_format(mm_transcode_support_type_callback type_callback, void *user_param)
466 for (idx = 0; idx < MM_CONTAINER_NUM; idx++) {
467 if (type_callback(idx, user_param) == false) {
468 LOGE("error occured. idx[%d]", idx);
473 return MM_ERROR_NONE;
476 int mm_transcode_get_supported_video_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
480 for (idx = 0; idx < MM_VIDEOENCODER_H264; idx++) {
481 if (type_callback(idx, user_param) == false) {
482 LOGE("error occured. idx[%d]", idx);
487 return MM_ERROR_NONE;
490 int mm_transcode_get_supported_audio_encoder(mm_transcode_support_type_callback type_callback, void *user_param)
494 for (idx = 0; idx < MM_AUDIOENCODER_NO_USE; idx++) {
495 if (type_callback(idx, user_param) == false) {
496 LOGE("error occured. idx[%d]", idx);
501 return MM_ERROR_NONE;