4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 /*=======================================================================================
22 =======================================================================================*/
30 #include <media_format.h>
31 #include <streamrecorder.h>
32 #include <streamrecorder_private.h>
37 /*-----------------------------------------------------------------------
38 | GLOBAL VARIABLE DEFINITIONS: |
39 -----------------------------------------------------------------------*/
40 #define EXPORT_API __attribute__((__visibility__("default")))
42 #define PACKAGE "recorder_testsuite"
45 GIOChannel *stdin_channel;
51 static GTimer *timer = NULL;
54 /*-----------------------------------------------------------------------
55 | GLOBAL CONSTANT DEFINITIONS: |
56 -----------------------------------------------------------------------*/
59 /*-----------------------------------------------------------------------
60 | IMPORTED VARIABLE DECLARATIONS: |
61 -----------------------------------------------------------------------*/
64 /*-----------------------------------------------------------------------
65 | IMPORTED FUNCTION DECLARATIONS: |
66 -----------------------------------------------------------------------*/
69 /*-----------------------------------------------------------------------
71 -----------------------------------------------------------------------*/
74 #define DISPLAY_W_320 320 /*for direct FB*/
75 #define DISPLAY_H_240 240 /*for direct FB*/
78 #define SRC_VIDEO_FRAME_RATE_15 15 /* video input frame rate */
79 #define SRC_VIDEO_FRAME_RATE_30 30 /* video input frame rate */
80 #define IMAGE_ENC_QUALITY 85 /* quality of jpeg */
82 #define MAX_FILE_SIZE_FOR_MMS (250 * 1024)
84 #define EXT_JPEG "jpg"
90 #define TARGET_FILENAME_PATH "/opt/usr/media/"
91 #define IMAGE_CAPTURE_EXIF_PATH TARGET_FILENAME_PATH"exif.raw"
92 #define TARGET_FILENAME_VIDEO TARGET_FILENAME_PATH"test.mp4"
93 #define TARGET_FILENAME_AUDIO TARGET_FILENAME_PATH"test_rec_audio.m4a"
94 #define CAPTURE_FILENAME_LEN 256
96 #define AUDIO_SOURCE_SAMPLERATE_AAC 44100
97 #define AUDIO_SOURCE_SAMPLERATE_AMR 8000
98 #define AUDIO_SOURCE_FORMAT MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE
99 #define AUDIO_SOURCE_CHANNEL_AAC 2
100 #define AUDIO_SOURCE_CHANNEL_AMR 1
101 #define VIDEO_ENCODE_BITRATE 40000000 /* bps */
103 #define CHECK_MM_ERROR(expr) \
108 printf("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \
115 #define SAFE_FREE(x) if (x) { g_free(x); x = NULL; }
125 * Enumerations for command
127 #define SENSOR_WHITEBALANCE_NUM 10
128 #define SENSOR_COLOR_TONE_NUM 31
129 #define SENSOR_FLIP_NUM 3
130 #define SENSOR_PROGRAM_MODE_NUM 15
131 #define SENSOR_FOCUS_NUM 6
132 #define SENSOR_INPUT_ROTATION 4
133 #define SENSOR_AF_SCAN_NUM 4
134 #define SENSOR_ISO_NUM 8
135 #define SENSOR_EXPOSURE_NUM 9
136 #define SENSOR_IMAGE_FORMAT 9
139 /*-----------------------------------------------------------------------
140 | LOCAL CONSTANT DEFINITIONS: |
141 -----------------------------------------------------------------------*/
143 MODE_LIVE_BUFFER_I420_VIDEO , /*video capturing mode from live buffer I420 using software encoder*/
144 MODE_LIVE_BUFFER_NV12_VIDEO_SW , /*video capturing mode from live buffer NV12 using software encoder */
145 MODE_LIVE_BUFFER_NV12_VIDEO_HW , /*video capturing mode from live buffer NV12 using hardware encoder*/
154 /*-----------------------------------------------------------------------
155 | LOCAL DATA TYPE DEFINITIONS: |
156 -----------------------------------------------------------------------*/
157 typedef struct _mstreamrecorder_handle {
158 streamrecorder_h recorder;
159 int mode; /*video/audio(recording) mode */
163 unsigned long long elapsed_time;
164 } mstreamrecorder_handle_t;
167 /*---------------------------------------------------------------------------
168 | LOCAL VARIABLE DEFINITIONS: |
169 ---------------------------------------------------------------------------*/
170 static mstreamrecorder_handle_t *hmstreamrecorder ;
172 /*---------------------------------------------------------------------------
173 | LOCAL FUNCTION PROTOTYPES: |
174 ---------------------------------------------------------------------------*/
175 static void print_menu();
176 static gboolean cmd_input(GIOChannel *channel);
177 static gboolean init(int type);
178 static gboolean mode_change();
181 void _recording_status_cb(unsigned long long elapsed_time, unsigned long long file_size, void *user_data)
183 printf("elapsed time :%lld, file_size :%lld\n", elapsed_time, file_size);
186 void _recording_limit_reached_cb(streamrecorder_recording_limit_type_e type, void *user_data)
188 g_print("limited!! %d\n", type);
189 int *ischeck = (int *)user_data;
192 static inline void flush_stdin()
195 while ((ch = getchar()) != EOF && ch != '\n');
199 static void print_menu()
201 switch (hmstreamrecorder->menu_state) {
202 case MENU_STATE_MAIN:
203 if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO || hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
204 g_print("\n\t=======================================\n");
205 if (recorder_state <= STREAMRECORDER_STATE_NONE) {
206 g_print("\t '1' Start Recording\n");
207 g_print("\t 'b' back\n");
208 } else if (recorder_state == STREAMRECORDER_STATE_RECORDING) {
209 g_print("\t 'p' Pause Recording\n");
210 g_print("\t 'c' Cancel\n");
211 g_print("\t 's' Save\n");
212 } else if (recorder_state == STREAMRECORDER_STATE_PAUSED) {
213 g_print("\t 'r' Resume Recording\n");
214 g_print("\t 's' Save\n");
220 LOGE("unknow menu state !!\n");
226 media_packet_h streamrecorder_make_media_packet(int video, void *data, int size)
229 media_packet_h out_pkt;
230 media_format_h output_fmt;
231 if (media_format_create(&output_fmt)) {
232 g_print("media_format_create failed\n");
237 if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
238 media_format_set_video_mime(output_fmt, MEDIA_FORMAT_NV12);
239 } else if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO) {
240 media_format_set_video_mime(output_fmt, MEDIA_FORMAT_I420);
242 media_format_set_video_width(output_fmt, 1280);
243 media_format_set_video_height(output_fmt, 720);
244 if (media_format_set_video_frame_rate(output_fmt, 30)) {
245 g_print("media_format_set_video_frame_rate failed\n");
249 media_format_set_audio_mime(output_fmt, MEDIA_FORMAT_PCM);
250 media_format_set_audio_channel(output_fmt, 1);
251 media_format_set_audio_samplerate(output_fmt, 44100);
252 /*media_format_set_audio_bit(core->output_fmt, info->bit);*/
254 if (media_packet_create(output_fmt, NULL, NULL, &out_pkt)) {
255 g_print("create video media_packet failed\n");
258 if (media_packet_alloc(out_pkt)) {
259 g_print("video media_packet alloc failed\n");
262 media_packet_get_buffer_data_ptr(out_pkt, (void **)&pkt_data);
263 memcpy((char *)pkt_data, data, size);
264 if (media_packet_set_buffer_size(out_pkt, (uint64_t)(size))) {
265 g_print("video set_buffer_size failed\n");
272 void feed_video_es(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data)
276 GstMapInfo map = GST_MAP_INFO_INIT;
277 media_packet_h out_pkt = NULL;
279 gst_buffer_ref(buffer);
281 n = gst_buffer_n_memory(buffer);
283 mem = gst_buffer_peek_memory(buffer, n-1);
285 gst_memory_map(mem, &map, GST_MAP_READ);
286 out_pkt = streamrecorder_make_media_packet(1, map.data, map.size);
287 gst_memory_unmap(mem, &map);
289 media_packet_set_pts(out_pkt, buffer->pts);
290 media_packet_set_extra(out_pkt, buffer);
291 streamrecorder_push_stream_buffer(hmstreamrecorder->recorder, out_pkt);
296 GstElement *vpipeline, *vconvert, *vsrc, *vfakesink, *vcaps;
297 void close_pipeline(void)
300 gst_object_unref(vpipeline);
302 gst_object_unref(vsrc);
304 gst_object_unref(vfakesink);
306 gst_object_unref(vcaps);
308 gst_object_unref(vconvert);
312 int __feed_buffer_test(MMHandleType handle, int mode)
315 GstCaps *caps = NULL;
316 g_print("creating __feed_buffer_test pipeline\n");
319 /* create video pipeline */
320 vpipeline = gst_pipeline_new(NULL);
322 g_print("pipeline create fail\n");
325 if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
326 vsrc = gst_element_factory_make("videotestsrc", NULL);
328 g_print("src element creation failed\n");
332 vsrc = gst_element_factory_make("videotestsrc", NULL);
334 g_print("src element creation failed\n");
338 if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
339 vconvert = gst_element_factory_make("videoconvert", NULL);
341 g_print("convert element creation failed\n");
345 vcaps = gst_element_factory_make("capsfilter", NULL);
347 g_print("capsfilter element creation failed\n");
350 if (mode == MODE_LIVE_BUFFER_I420_VIDEO) {
351 caps = gst_caps_new_simple("video/x-raw",
352 "format", G_TYPE_STRING, "I420",
353 "width", G_TYPE_INT, 1280,
354 "height", G_TYPE_INT, 720, NULL);
355 } else if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
356 caps = gst_caps_new_simple("video/x-raw",
357 "format", G_TYPE_STRING, "NV12",
358 "width", G_TYPE_INT, 1280,
359 "height", G_TYPE_INT, 720,
360 "framerate", GST_TYPE_FRACTION, 30, 1, NULL);
362 g_object_set(vcaps, "caps", caps, NULL);
363 gst_caps_unref(caps);
365 vfakesink = gst_element_factory_make("fakesink", NULL);
367 g_print("video fakesink creation failed\n");
370 g_object_set(GST_OBJECT(vfakesink), "signal-handoffs", TRUE, NULL);
371 g_signal_connect(vfakesink, "handoff", G_CALLBACK(feed_video_es), handle);
373 if (mode == MODE_LIVE_BUFFER_I420_VIDEO) {
374 gst_bin_add_many(GST_BIN(vpipeline), vsrc, vcaps, vfakesink, NULL);
376 if (!gst_element_link_many(vsrc, vcaps, vfakesink, NULL)) {
377 GST_WARNING("Can't link elements video pipeline");
380 } else if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
381 gst_bin_add_many(GST_BIN(vpipeline), vsrc, vconvert, vcaps, vfakesink, NULL);
383 if (!gst_element_link_many(vsrc , vconvert, vcaps, vfakesink, NULL)) {
384 GST_WARNING("Can't link elements video pipeline");
388 g_print("Linking done video pipeline\n");
391 GstElement *a_pipeline, *asrc, *afakesink;
392 /* create common elements */
393 a_pipeline = gst_pipeline_new(NULL);
395 g_print("pipeline create fail\n");
398 asrc = gst_element_factory_make("audiotestsrc", NULL);
400 g_print("src element creation failed\n");
403 afakesink = gst_element_factory_make("fakesink", NULL);
405 g_print("audio fakesink creation failed\n");
408 /* connect handoff */
409 g_object_set(GST_OBJECT(afakesink), "signal-handoffs", TRUE, NULL);
410 g_signal_connect(fakesink, "handoff", G_CALLBACK(feed_audio_es), handle);
412 gst_bin_add_many(GST_BIN(v_pipeline), asrc, afakesink, NULL);
415 if (!gst_element_link_many(asrc, afakesink, NULL)) {
416 GST_WARNING("Can't link elements audio pipeline");
419 g_print("Linking done audio pipeline\n");
420 gst_element_set_state(apipeline, GST_STATE_PLAYING);
422 gst_element_set_state(vpipeline, GST_STATE_PLAYING);
423 g_print("feed_task pipeline is playing\n");
429 static void main_menu(gchar buf)
433 if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO || hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
434 if (recorder_state == STREAMRECORDER_STATE_NONE) {
436 case '1': /* Start Recording*/
437 hmstreamrecorder->elapsed_time = 0;
438 err = streamrecorder_start(hmstreamrecorder->recorder);
440 g_timer_reset(timer);
441 err = __feed_buffer_test(hmstreamrecorder->recorder, hmstreamrecorder->mode);
442 if (err != MM_ERROR_NONE)
444 g_print("Rec star in live buffer 0x%x", err);
446 LOGE("Rec start live buffer 0x%x", err);
448 recorder_state = STREAMRECORDER_STATE_RECORDING;
452 hmstreamrecorder->menu_state = MENU_STATE_MAIN;
457 g_print("\t Invalid input \n");
460 } else if (recorder_state == STREAMRECORDER_STATE_RECORDING || recorder_state == STREAMRECORDER_STATE_PAUSED) {
462 if (recorder_state == STREAMRECORDER_STATE_RECORDING) {
463 case 'p': /* Pause Recording*/
464 g_print("*Pause!\n");
465 err = streamrecorder_pause(hmstreamrecorder->recorder);
468 LOGE("Rec pause streamrecorder_pause = %x", err);
470 recorder_state = STREAMRECORDER_STATE_PAUSED;
474 case 'r': /* Resume Recording*/
475 g_print("*Resume!\n");
476 err = streamrecorder_start(hmstreamrecorder->recorder);
478 LOGE("Rec start streamrecorder_record = %x", err);
480 recorder_state = STREAMRECORDER_STATE_RECORDING;
484 case 'c': /* Cancel*/
485 g_print("*Cancel Recording !\n");
487 err = streamrecorder_cancel(hmstreamrecorder->recorder);
490 LOGE("Cancel recording streamrecorder_cancel = %x", err);
492 recorder_state = STREAMRECORDER_STATE_NONE;
496 g_print("*Save Recording!\n");
497 g_timer_reset(timer);
499 err = streamrecorder_commit(hmstreamrecorder->recorder);
502 LOGE("Save recording streamrecorder_commit = %x", err);
504 recorder_state = STREAMRECORDER_STATE_NONE;
508 g_print("\t Invalid input \n");
512 LOGE("Wrong streamrecorder state, check status!!");
515 g_print("\t Invalid mode, back to upper menu \n");
516 hmstreamrecorder->menu_state = MENU_STATE_MAIN;
523 * This function is to execute command.
525 * @param channel [in] 1st parameter
527 * @return This function returns TRUE/FALSE
531 static gboolean cmd_input(GIOChannel *channel)
535 GError *g_error = NULL;
539 g_io_channel_read_line(channel, &buf, &read_size, NULL, &g_error);
541 LOGD("g_io_channel_read_chars error");
542 g_error_free(g_error);
549 LOGD("Menu Status : %d", hmstreamrecorder->menu_state);
550 switch (hmstreamrecorder->menu_state) {
551 case MENU_STATE_MAIN:
563 LOGD("No read input");
569 static gboolean init(int type)
574 if (!hmstreamrecorder)
577 if (!hmstreamrecorder->recorder)
580 /*================================================================================
582 *=================================================================================*/
583 if (type == MODE_LIVE_BUFFER_I420_VIDEO || type == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
584 if (type == MODE_LIVE_BUFFER_I420_VIDEO) {
585 err = streamrecorder_set_video_source_format(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_SOURCE_FORMAT_I420);
587 LOGE("Init fail. (%x)", err);
590 } else if (type == MODE_LIVE_BUFFER_NV12_VIDEO_SW) {
591 err = streamrecorder_set_video_source_format(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_SOURCE_FORMAT_NV12);
593 LOGE("Init fail. (%x)", err);
597 err = streamrecorder_set_file_format(hmstreamrecorder->recorder, STREAMRECORDER_FILE_FORMAT_MP4);
599 LOGE("aInit fail. (%x)", err);
602 err = streamrecorder_set_video_encoder(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_CODEC_MPEG4);
604 LOGE("bInit fail. (%x)", err);
607 err = streamrecorder_set_video_resolution(hmstreamrecorder->recorder, 1280, 720);
609 LOGE("dInit fail. (%x)", err);
612 err = streamrecorder_set_video_framerate(hmstreamrecorder->recorder, 30);
614 LOGE("dInit fail. (%x)", err);
617 err = streamrecorder_set_filename(hmstreamrecorder->recorder, TARGET_FILENAME_VIDEO);
619 LOGE("dInit fail. (%x)", err);
624 streamrecorder_set_recording_status_cb(hmstreamrecorder->recorder, _recording_status_cb, NULL);
625 streamrecorder_set_recording_limit_reached_cb(hmstreamrecorder->recorder, _recording_limit_reached_cb, &ischeck);
632 LOGE("init failed.");
636 static gboolean init_handle()
638 hmstreamrecorder->mode = 0; /* image(capture)/video(recording) mode */
639 hmstreamrecorder->menu_state = MENU_STATE_MAIN;
640 hmstreamrecorder->isMute = FALSE;
641 hmstreamrecorder->elapsed_time = 0;
642 hmstreamrecorder->fps = SRC_VIDEO_FRAME_RATE_15; /*SRC_VIDEO_FRAME_RATE_30;*/
647 * This function is to change streamrecorder mode.
649 * @param type [in] image(capture)/video(recording) mode
651 * @return This function returns TRUE/FALSE
653 * @see other functions
655 static gboolean mode_change()
657 int err = STREAMRECORDER_ERROR_NONE;
658 int state = STREAMRECORDER_STATE_NONE;
659 char media_type = '\0';
662 err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state);
663 if (state != STREAMRECORDER_STATE_NONE) {
664 if ((state == STREAMRECORDER_STATE_RECORDING) || (state == STREAMRECORDER_STATE_PAUSED)) {
665 LOGD("streamrecorder_cancel");
666 err = streamrecorder_cancel(hmstreamrecorder->recorder);
669 LOGE("exit streamrecorder_cancel = %x", err);
674 err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state);
675 if (state == STREAMRECORDER_STATE_PREPARED) {
676 LOGD("streamrecorder_destroy");
677 streamrecorder_unprepare(hmstreamrecorder->recorder);
680 err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state);
681 if (state == STREAMRECORDER_STATE_CREATED) {
682 LOGD("streamrecorder_destroy");
683 streamrecorder_destroy(hmstreamrecorder->recorder);
688 streamrecorder_create(&hmstreamrecorder->recorder);
689 g_get_current_time(&previous);
690 g_timer_reset(timer);
692 g_print("\n\t=======================================\n");
693 g_print("\t RECORDER_TESTSUIT\n");
694 g_print("\t=======================================\n");
695 g_print("\t '1' i420 sw buffer - Video\n");
696 g_print("\t '2' nv12 sw buffer - Video\n");
697 g_print("\t 'q' Exit\n");
698 g_print("\t=======================================\n");
700 g_print("\t Enter the media type:\n\t");
702 err = scanf("%c", &media_type);
704 g_print("\t!!!read input error!!!\n");
708 switch (media_type) {
710 hmstreamrecorder->mode = MODE_LIVE_BUFFER_I420_VIDEO;
711 streamrecorder_enable_source_buffer(hmstreamrecorder->recorder, STREAMRECORDER_SOURCE_VIDEO);
715 hmstreamrecorder->mode = MODE_LIVE_BUFFER_NV12_VIDEO_SW;
716 streamrecorder_enable_source_buffer(hmstreamrecorder->recorder, STREAMRECORDER_SOURCE_VIDEO);
720 g_print("\t Quit Streamrecorder Testsuite!!\n");
721 hmstreamrecorder->mode = -1;
722 if (g_main_loop_is_running(g_loop))
723 g_main_loop_quit(g_loop);
727 g_print("\t Invalid media type(%d)\n", media_type);
732 g_timer_reset(timer);
734 if (!init(hmstreamrecorder->mode)) {
735 g_print("hmstreamrecorder->mode = %d\n", hmstreamrecorder->mode);
736 LOGE("testsuite init() failed.");
740 g_timer_reset(timer);
742 err = streamrecorder_prepare(hmstreamrecorder->recorder);
743 LOGD("streamrecorder_start() : %12.6lfs", g_timer_elapsed(timer, NULL));
746 LOGE("streamrecorder_prepare = %x", err);
750 g_get_current_time(¤t);
751 timersub(¤t, &previous, &result);
752 LOGD("Streamrecorder Starting Time : %ld.%lds", result.tv_sec, result.tv_usec);
759 * This function is the example main function for recorder API.
763 * @return This function returns 0.
765 * @see other functions
767 int main(int argc, char **argv)
771 timer = g_timer_new();
773 gst_init(&argc, &argv);
775 LOGD("gst_init() : %12.6lfs", g_timer_elapsed(timer, NULL));
777 hmstreamrecorder = (mstreamrecorder_handle_t *) g_malloc0(sizeof(mstreamrecorder_handle_t));
779 recorder_state = STREAMRECORDER_STATE_NONE;
781 g_timer_reset(timer);
783 bret = mode_change();
789 g_loop = g_main_loop_new(NULL, FALSE);
791 stdin_channel = g_io_channel_unix_new(fileno(stdin));/* read from stdin */
792 g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)cmd_input, NULL);
794 LOGD("RUN main loop");
796 g_main_loop_run(g_loop);
798 LOGD("STOP main loop");
802 g_timer_destroy(timer);
806 g_free(hmstreamrecorder);
807 g_main_loop_unref(g_loop);
808 g_io_channel_unref(stdin_channel);