| /* |
| * Copyright (c) 2014-2015, Freescale Semiconductor, Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <semaphore.h> |
| #include <pthread.h> |
| #include <signal.h> |
| #include <getopt.h> |
| #define __USE_LARGEFILE64 |
| #include <sys/statvfs.h> |
| |
| #include "recorder_engine.h" |
| |
| #define LOG_ERROR printf |
| #define LOG_INFO printf |
| #define LOG_DEBUG printf |
| |
| #define LATEST_REMAIN_SPACE_SIZE (50*1024*1024) |
| |
| #define START_MEDIATIME_INFO_THREAD(thread, recorder)\ |
| do{\ |
| if (thread == NULL){\ |
| exit_thread = RE_BOOLEAN_FALSE;\ |
| pthread_create(&(thread), NULL, display_media_time, (recorder));\ |
| }\ |
| }while(0) |
| |
| #define STOP_MEDIATIME_INFO_THREAD(thread)\ |
| do{\ |
| if((thread && exit_thread == RE_BOOLEAN_FALSE)) {\ |
| exit_thread = RE_BOOLEAN_TRUE;\ |
| pthread_join ((thread), NULL);\ |
| (thread)=NULL;\ |
| }\ |
| }while(0) |
| |
| |
| #define START_SHOW_MEDIATIME_INFO \ |
| do{\ |
| bstartmediatime = RE_BOOLEAN_TRUE;\ |
| }while(0) |
| |
| #define STOP_SHOW_MEDIATIME_INFO \ |
| do{\ |
| bstartmediatime = RE_BOOLEAN_FALSE;\ |
| }while(0) |
| |
| #define START_MESSAGE_PROCESS_THREAD(thread, recorder)\ |
| do{\ |
| if (thread == NULL){\ |
| exit_thread = RE_BOOLEAN_FALSE;\ |
| pthread_create(&(thread), NULL, process_message, (recorder));\ |
| }\ |
| }while(0) |
| |
| #define STOP_MESSAGE_PROCESS_THREAD(thread)\ |
| do{\ |
| if((thread && exit_thread == RE_BOOLEAN_FALSE)) {\ |
| exit_thread = RE_BOOLEAN_TRUE;\ |
| sem_post(&grecordersem);\ |
| pthread_join ((thread), NULL);\ |
| (thread)=NULL;\ |
| }\ |
| }while(0) |
| |
| #define RECORDER_START \ |
| do{\ |
| post_message (MESSAGE_START);\ |
| }while(0) |
| |
| #define RECORDER_STOP \ |
| do{\ |
| post_message (MESSAGE_STOP);\ |
| }while(0) |
| |
| #define RECORDER_PAUSE \ |
| do{\ |
| post_message (MESSAGE_PAUSE);\ |
| }while(0) |
| |
| #define RECORDER_RESUME \ |
| do{\ |
| post_message (MESSAGE_RESUME);\ |
| }while(0) |
| |
| #define RECORDER_TAKE_SNAPSHOT \ |
| do{\ |
| post_message (MESSAGE_SNAPSHOT);\ |
| }while(0) |
| |
| #define RECORDER_RESET \ |
| do{\ |
| post_message (MESSAGE_RESET);\ |
| }while(0) |
| |
| typedef enum{ |
| MESSAGE_NULL, |
| MESSAGE_START, |
| MESSAGE_STOP, |
| MESSAGE_PAUSE, |
| MESSAGE_RESUME, |
| MESSAGE_SNAPSHOT, |
| MESSAGE_RESET |
| }RecorderMessage; |
| |
| typedef struct { |
| REuint32 list; |
| REuint32 audio_source; |
| REuint32 sample_rate; |
| REuint32 channel; |
| REuint32 video_source; |
| REuint32 camera_id; |
| REuint32 video_format; |
| REuint32 width; |
| REuint32 height; |
| REuint32 fps; |
| REboolean add_time_stamp; |
| REuint32 video_effect; |
| REuint32 video_detect; |
| REuint32 preview_left; |
| REuint32 preview_top; |
| REuint32 preview_width; |
| REuint32 preview_height; |
| REuint32 disable_viewfinder; |
| REuint32 preview_buffer; |
| REuint32 audio_encoder; |
| REuint32 audio_bitrate; |
| REuint32 video_encoder; |
| REuint32 video_bitrate; |
| REuint32 container_format; |
| REchar path[1024]; |
| REchar host[32]; |
| REuint32 port; |
| REuint32 file_count; |
| REuint32 duration; |
| REuint64 file_size; |
| REuint32 aging; |
| REuint32 verbose; |
| REboolean use_default_filename; |
| }REOptions; |
| |
| static pthread_t media_time_thread = NULL; |
| static pthread_t message_process_thread = NULL; |
| static REboolean exit_thread = RE_BOOLEAN_FALSE; |
| static REboolean bstartmediatime = RE_BOOLEAN_FALSE; |
| static REchar path[1024]; |
| static REboolean bAgingtest = RE_BOOLEAN_FALSE; |
| static sem_t grecordersem; |
| static RecorderMessage latest_message = MESSAGE_NULL; |
| |
| static volatile sig_atomic_t quit_flag = 0; |
| |
| static void signal_handler(int signum) |
| { |
| quit_flag = 1; |
| } |
| |
| static REuint64 get_storage_free_size (char *dirname) |
| { |
| struct statvfs64 fsdata; |
| REuint64 free_size; |
| |
| if (statvfs64(dirname, &fsdata) < 0) { |
| LOG_ERROR ("get storage free size fail.\n"); |
| return 0; |
| } |
| |
| free_size = fsdata.f_bfree * fsdata.f_bsize; |
| return free_size; |
| } |
| |
| static void monitor_storage_free_size (RecorderEngine* recorder) |
| { |
| if (get_storage_free_size (path) < LATEST_REMAIN_SPACE_SIZE) { |
| LOG_INFO ("storage free space is less then %d. stop recording", \ |
| LATEST_REMAIN_SPACE_SIZE); |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| } |
| } |
| |
| static void display_media_time (void* param) |
| { |
| RecorderEngine* recorder = (RecorderEngine*)param; |
| REtime sCur; |
| REuint32 Hours; |
| REuint32 Minutes; |
| REuint32 Seconds; |
| |
| while(exit_thread == RE_BOOLEAN_FALSE) |
| { |
| if (bstartmediatime) |
| { |
| sCur = 0; |
| if(RE_RESULT_SUCCESS == recorder->get_media_time ((RecorderEngineHandle)recorder, &sCur)) |
| { |
| Hours = (sCur/1000000) / 3600; |
| Minutes = (sCur/ (60*1000000)) % 60; |
| Seconds = ((sCur %(3600*1000000)) % (60*1000000))/1000000; |
| printf("\r[Current Media Time] %03d:%02d:%02d", |
| Hours, Minutes, Seconds); |
| fflush(stdout); |
| } |
| |
| monitor_storage_free_size (recorder); |
| |
| usleep (500000); |
| } |
| else |
| usleep (50000); |
| } |
| |
| return; |
| } |
| |
| static int set_recoder_setting (RecorderEngine *recorder, REOptions * pOpt) |
| { |
| REuint64 free_size; |
| |
| /* Audio source interface */ |
| if (RE_RESULT_SUCCESS != recorder->set_audio_source ( |
| (RecorderEngineHandle)recorder, pOpt->audio_source)) { |
| LOG_ERROR ("set audio source fail.\n"); |
| return -1; |
| } |
| if (RE_RESULT_SUCCESS != recorder->set_audio_sample_rate ( |
| (RecorderEngineHandle)recorder, pOpt->sample_rate)) { |
| LOG_ERROR ("set audio sample rate fail.\n"); |
| return -1; |
| } |
| if (RE_RESULT_SUCCESS != recorder->set_audio_channel ( |
| (RecorderEngineHandle)recorder, pOpt->channel)) { |
| LOG_ERROR ("set audio channel fail.\n"); |
| return -1; |
| } |
| |
| /* Camera interface */ |
| if (RE_RESULT_SUCCESS != recorder->set_video_source ( |
| (RecorderEngineHandle)recorder, pOpt->video_source)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| if (RE_RESULT_SUCCESS != recorder->set_camera_id ( |
| (RecorderEngineHandle)recorder, pOpt->camera_id)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| { |
| RERawVideoSettings video_property; |
| video_property.videoFormat = pOpt->video_format; |
| video_property.width = pOpt->width; |
| video_property.height = pOpt->height; |
| video_property.framesPerSecond = pOpt->fps; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_camera_output_settings ( |
| (RecorderEngineHandle)recorder, &video_property)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| /* View finder interface */ |
| recorder->disable_viewfinder ((RecorderEngineHandle)recorder, pOpt->disable_viewfinder); |
| { |
| REVideoRect rect; |
| rect.left = pOpt->preview_left; |
| rect.top = pOpt->preview_top; |
| rect.width = pOpt->preview_width; |
| rect.height = pOpt->preview_height; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_preview_region ( |
| (RecorderEngineHandle)recorder, &rect)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| /* Preview buffer after capture */ |
| if (RE_RESULT_SUCCESS != recorder->need_preview_buffer ( |
| (RecorderEngineHandle)recorder, pOpt->preview_buffer)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| |
| /* Video time stamp and video effect */ |
| recorder->add_time_stamp ((RecorderEngineHandle)recorder, pOpt->add_time_stamp); |
| recorder->add_video_effect ((RecorderEngineHandle)recorder, pOpt->video_effect); |
| recorder->add_video_detect ((RecorderEngineHandle)recorder, pOpt->video_detect); |
| |
| /* Audio encoder interface */ |
| { |
| REAudioEncoderSettings audio_encoder; |
| audio_encoder.encoderType = pOpt->audio_encoder; |
| audio_encoder.bitRate = pOpt->audio_bitrate; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_audio_encoder_settings ( |
| (RecorderEngineHandle)recorder, &audio_encoder)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| /* Video encoder interface */ |
| { |
| REVideoEncoderSettings video_encoder; |
| video_encoder.encoderType = pOpt->video_encoder; |
| video_encoder.bitRate = pOpt->video_bitrate; |
| video_encoder.IFrameIntervalMs = 0; |
| video_encoder.profile = 0; |
| video_encoder.level = 0; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_video_encoder_settings ( |
| (RecorderEngineHandle)recorder, &video_encoder)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| /* Recorded output interface */ |
| if (RE_RESULT_SUCCESS != recorder->set_container_format ( |
| (RecorderEngineHandle)recorder, pOpt->container_format)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| |
| if (pOpt->host[0]) |
| recorder->set_rtp_host ((RecorderEngineHandle)recorder, pOpt->host, pOpt->port); |
| |
| /* fileCount is 0 means unlimited */ |
| if (RE_RESULT_SUCCESS != recorder->set_file_count ( |
| (RecorderEngineHandle)recorder, pOpt->file_count)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| if (pOpt->duration) { |
| if (RE_RESULT_SUCCESS != recorder->set_max_file_duration ( |
| (RecorderEngineHandle)recorder, pOpt->duration)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| free_size = get_storage_free_size(path); |
| if (pOpt->file_size) { |
| if (RE_RESULT_SUCCESS != recorder->set_max_file_size_bytes ( |
| (RecorderEngineHandle)recorder, |
| pOpt->file_size <= free_size ? pOpt->file_size:free_size)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } else { |
| if (RE_RESULT_SUCCESS != recorder->set_max_file_size_bytes ( |
| (RecorderEngineHandle)recorder, free_size)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int set_recoder_setting_snap_shot (RecorderEngine *recorder, REOptions * pOpt) |
| { |
| REuint64 free_size; |
| |
| if (pOpt->use_default_filename == RE_BOOLEAN_TRUE) { |
| strcpy(pOpt->path, "./grecorder_output.jpg"); |
| } |
| free_size = get_storage_free_size(path); |
| if (free_size < LATEST_REMAIN_SPACE_SIZE) { |
| LOG_ERROR ("storage free size is less than: %d is: %lld\n", |
| LATEST_REMAIN_SPACE_SIZE, free_size); |
| return -1; |
| } |
| if (RE_RESULT_SUCCESS != recorder->set_output_file_path ( |
| (RecorderEngineHandle)recorder, pOpt->path)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| |
| { |
| REOutputFileSettings file_setting; |
| file_setting.interleaveMs = 0; |
| file_setting.movieTimeScale = 0; |
| file_setting.audioTimeScale = 0; |
| file_setting.videoTimeScale = 0; |
| file_setting.rotation = 0; |
| file_setting.longitudex = 0; |
| file_setting.latitudex = 0; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_output_file_settings ( |
| (RecorderEngineHandle)recorder, &file_setting)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int set_recoder_setting_video (RecorderEngine *recorder, REOptions * pOpt) |
| { |
| REuint64 free_size; |
| |
| if (pOpt->use_default_filename == RE_BOOLEAN_TRUE) { |
| switch (pOpt->container_format) { |
| case RE_OUTPUT_FORMAT_DEFAULT: |
| case RE_OUTPUT_FORMAT_MOV: |
| strcpy(pOpt->path, "./grecorder_output.mp4"); |
| break; |
| case RE_OUTPUT_FORMAT_MKV: |
| strcpy(pOpt->path, "./grecorder_output.mkv"); |
| break; |
| case RE_OUTPUT_FORMAT_AVI: |
| strcpy(pOpt->path, "./grecorder_output.avi"); |
| break; |
| case RE_OUTPUT_FORMAT_FLV: |
| strcpy(pOpt->path, "./grecorder_output.flv"); |
| break; |
| case RE_OUTPUT_FORMAT_TS: |
| strcpy(pOpt->path, "./grecorder_output.ts"); |
| break; |
| default: |
| strcpy(pOpt->path, "./grecorder_output.mp4"); |
| break; |
| } |
| } |
| free_size = get_storage_free_size(path); |
| if (free_size < LATEST_REMAIN_SPACE_SIZE) { |
| LOG_ERROR ("storage free size is less than: %d is: %lld\n", |
| LATEST_REMAIN_SPACE_SIZE, free_size); |
| return -1; |
| } |
| if (RE_RESULT_SUCCESS != recorder->set_output_file_path ( |
| (RecorderEngineHandle)recorder, pOpt->path)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| |
| { |
| REOutputFileSettings file_setting; |
| file_setting.interleaveMs = 0; |
| file_setting.movieTimeScale = 0; |
| file_setting.audioTimeScale = 0; |
| file_setting.videoTimeScale = 0; |
| file_setting.rotation = 0; |
| file_setting.longitudex = 0; |
| file_setting.latitudex = 0; |
| |
| if (RE_RESULT_SUCCESS != recorder->set_output_file_settings ( |
| (RecorderEngineHandle)recorder, &file_setting)) { |
| LOG_ERROR ("set video source fail.\n"); |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| void post_message (RecorderMessage message) |
| { |
| latest_message = message; |
| sem_post(&grecordersem); |
| } |
| |
| static void process_message (void* param) |
| { |
| RecorderEngine* recorder = (RecorderEngine*)param; |
| |
| while(exit_thread == RE_BOOLEAN_FALSE) |
| { |
| latest_message = MESSAGE_NULL; |
| sem_wait(&grecordersem); |
| |
| LOG_INFO ("process_message: %d\n", latest_message); |
| switch (latest_message) { |
| case MESSAGE_START: |
| if (RE_RESULT_SUCCESS == recorder->start((RecorderEngineHandle)recorder)) { |
| START_SHOW_MEDIATIME_INFO; |
| LOG_INFO ("start recording\n"); |
| } else |
| LOG_ERROR ("start recording failed\n"); |
| break; |
| case MESSAGE_STOP: |
| recorder->stop((RecorderEngineHandle)recorder); |
| break; |
| case MESSAGE_PAUSE: |
| recorder->pause((RecorderEngineHandle)recorder); |
| break; |
| case MESSAGE_RESUME: |
| recorder->resume((RecorderEngineHandle)recorder); |
| break; |
| case MESSAGE_SNAPSHOT: |
| recorder->take_snapshot((RecorderEngineHandle)recorder); |
| break; |
| case MESSAGE_RESET: |
| recorder->reset((RecorderEngineHandle)recorder); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| return; |
| } |
| |
| static void list_camera_capabilities (RecorderEngine* recorder) |
| { |
| REresult ret; |
| RERawVideoSettings videoProperty; |
| REuint32 index; |
| |
| LOG_INFO ("\nCamera Capebilities:\n\n"); |
| |
| for (index = 0; ; index ++) { |
| ret = recorder->get_camera_capabilities((RecorderEngineHandle)recorder, |
| index, &videoProperty); |
| if (ret == RE_RESULT_NO_MORE) { |
| break; |
| } |
| |
| LOG_INFO ("width: %d height: %d frame rate: %d\n", \ |
| videoProperty.width, videoProperty.height, \ |
| videoProperty.framesPerSecond); |
| } |
| } |
| |
| static int event_handler(void* context, REuint32 eventID, void* Eventpayload) |
| { |
| RecorderEngine* recorder = (RecorderEngine*) context; |
| switch(eventID) { |
| case RE_EVENT_ERROR_UNKNOWN: |
| LOG_ERROR ("error, post stop message.\n"); |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| break; |
| case RE_EVENT_PREVIEW_BUFFER: |
| LOG_INFO ("received preview buffer.\n"); |
| break; |
| case RE_EVENT_MAX_DURATION_REACHED: |
| case RE_EVENT_MAX_FILESIZE_REACHED: |
| LOG_ERROR ("reach max duration, post stop message.\n"); |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| break; |
| case RE_EVENT_OBJECT_POSITION: { |
| REVideoRect *object_pos = (REVideoRect *) Eventpayload; |
| LOG_INFO ("Object Detected. Position: [x:%d y:%d width: %d height: %d]\n", |
| object_pos->left, object_pos->top,object_pos->width,object_pos->height); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static void recorder_main_menu() |
| { |
| printf("\nSelect Command:\n"); |
| printf("\t[r]Start Record\n"); |
| printf("\t[n]Snapshot\n"); |
| printf("\t[t]Reset\n"); |
| printf("\t[s]Stop\n"); |
| printf("\t[x]Exit\n\n"); |
| } |
| |
| static int recorder_parse_options(int argc, char* argv[], REOptions * pOpt) |
| { |
| int ret = 0; |
| static int verbose; |
| static int list; |
| static int preview_buffer; |
| static int disable_viewfinder; |
| static int add_time_stamp; |
| int option_index = 0; |
| int c; |
| |
| while (1) |
| { |
| static char long_options_desc[][128] = { |
| {"list camera supported video property"}, |
| {"audio input: 0->default(mic), 1->mic, 2->audiotestsrc"}, |
| {"audio sample rate"}, |
| {"audio channel"}, |
| {"video input: 0->default(camera), 1->camera, 2->screen, 3->videotestsrc"}, |
| {"camera id: 0->/dev/video0, 1->/dev/video1"}, |
| {"camera output video format: 0->default(I420), 1->I420, 2->NV12, 3->YUYV, 4->UYVY"}, |
| {"camera output video width"}, |
| {"camera output video height"}, |
| {"camera output video FPS"}, |
| {"add date/time onto video"}, |
| {"video effect: 0->default(no effect),1:cube,2:mirror,3:squeeze,4:fisheye,5:gray,6:tunnel,7:twirl"}, |
| {"video detect: 0->default(no detect),1:face detect,2:faceblur"}, |
| {"preview video left"}, |
| {"preview video top"}, |
| {"preview video width"}, |
| {"preview video height"}, |
| {"disable view finder"}, |
| {"need preview buffer"}, |
| {"audio encoder type: 0->default(MP3), 1->MP3"}, |
| {"audio encoder bitrate(kbps)"}, |
| {"video encoder type: 0->default(H264), 1->H264, 2->MPEG4, 3->H263, 4->MPEG"}, |
| {"video encoder bitrate(kbps)"}, |
| {"media container format: 0->default(MOV), 1->MOV, 2->MKV, 3->AVI, 4->FLV, 5->TS"}, |
| {"output path"}, |
| {"RTP streaming host IP address"}, |
| {"RTP streaming port"}, |
| {"recording file count(0 means unlimited)"}, |
| {"max duration for recorded file(second)"}, |
| {"max file size for recorded file(Byte)"}, |
| {"display application log"}, |
| {0, 0, 0, 0} |
| }; |
| |
| static struct option long_options[] = |
| { |
| {"ls", no_argument, &list, 1}, |
| {"audio_source", required_argument, 0, 'a'}, |
| {"sample_rate", required_argument, 0, 's'}, |
| {"channel", required_argument, 0, 'c'}, |
| {"video_source", required_argument, 0, 'v'}, |
| {"camera_id", required_argument, 0, 'i'}, |
| {"video_format", required_argument, 0, 'u'}, |
| {"width", required_argument, 0, 'w'}, |
| {"height", required_argument, 0, 'e'}, |
| {"fps", required_argument, 0, 'f'}, |
| {"date_time", no_argument, &add_time_stamp, 1}, |
| {"video_effect", required_argument, 0, 'q'}, |
| {"video_detect", required_argument, 0, 'x'}, |
| {"preview_left", required_argument, 0, 'l'}, |
| {"preview_top", required_argument, 0, 't'}, |
| {"preview_width", required_argument, 0, 'b'}, |
| {"preview_height", required_argument, 0, 'n'}, |
| {"disable_viewfinder", no_argument, &disable_viewfinder, 1}, |
| {"preview_buffer", no_argument, &preview_buffer, 1}, |
| {"audio_encoder", required_argument, 0, 'g'}, |
| {"audio_bitrate", required_argument, 0, 'j'}, |
| {"video_encoder", required_argument, 0, 'k'}, |
| {"video_bitrate", required_argument, 0, 'm'}, |
| {"container_format", required_argument, 0, 't'}, |
| {"path", required_argument, 0, 'p'}, |
| {"host", required_argument, 0, 'o'}, |
| {"port", required_argument, 0, 'r'}, |
| {"file_count", required_argument, 0, 'n'}, |
| {"duration", required_argument, 0, 'd'}, |
| {"file_size", required_argument, 0, 'z'}, |
| {"verbose", no_argument, &verbose, 1}, |
| {0, 0, 0, 0} |
| }; |
| |
| c = getopt_long (argc, argv, "abcdefg", |
| long_options, &option_index); |
| |
| /* Detect the end of the options. */ |
| if (c == -1) |
| break; |
| |
| switch (c) |
| { |
| case 0: |
| /* If this option set a flag, do nothing else now. */ |
| if (long_options[option_index].flag != 0) |
| break; |
| printf ("option %s", long_options[option_index].name); |
| if (optarg) |
| printf (" with arg %s", optarg); |
| printf ("\n"); |
| break; |
| case 'a': |
| if (optarg) |
| pOpt->audio_source = atoi (optarg); |
| break; |
| case 's': |
| if (optarg) |
| pOpt->sample_rate = atoi (optarg); |
| break; |
| case 'w': |
| if (optarg) |
| pOpt->width = atoi (optarg); |
| break; |
| case 'e': |
| if (optarg) |
| pOpt->height = atoi (optarg); |
| break; |
| case 'u': |
| if (optarg) |
| pOpt->video_format = atoi (optarg); |
| break; |
| case 'f': |
| if (optarg) |
| pOpt->fps = atoi (optarg); |
| break; |
| case 'k': |
| if (optarg) |
| pOpt->video_encoder = atoi (optarg); |
| break; |
| case 't': |
| if (optarg) |
| pOpt->container_format = atoi (optarg); |
| break; |
| case 'q': |
| if (optarg) |
| pOpt->video_effect = atoi (optarg); |
| break; |
| case 'i': |
| if (optarg) |
| pOpt->camera_id = atoi (optarg); |
| break; |
| case 'v': |
| if (optarg) |
| pOpt->video_source = atoi (optarg); |
| break; |
| case 'n': |
| if (optarg) |
| pOpt->file_count = atoi (optarg); |
| break; |
| case 'z': |
| if (optarg) |
| pOpt->file_size = atoll (optarg); |
| break; |
| case 'o': |
| if (optarg && strlen (optarg) < 32) |
| strcpy (pOpt->host, optarg); |
| break; |
| case 'r': |
| if (optarg) |
| pOpt->port = atoi (optarg); |
| break; |
| case 'x': |
| if (optarg) |
| pOpt->video_detect = atoi (optarg); |
| break; |
| case 'h': |
| printf ("Usage: grecorder-1.0 [OPTION]\n"); |
| for (c = 0; long_options[c].name; ++c) { |
| printf ("-%c, --%s\r\t\t\t\t%s\n", long_options[c].val, |
| long_options[c].name, long_options_desc[c]); |
| } |
| ret = -1; |
| break; |
| case '?': |
| /* getopt_long already printed an error message. */ |
| printf ("Use -h to see help message.\n"); |
| printf ("Usage: grecorder-1.0 [OPTION]\n"); |
| for (c = 0; long_options[c].name; ++c) { |
| printf ("-%c, --%s\r\t\t\t\t%s\n", long_options[c].val, |
| long_options[c].name, long_options_desc[c]); |
| } |
| ret = -1; |
| break; |
| default: |
| break; |
| } |
| } |
| pOpt->verbose = verbose; |
| pOpt->list = list; |
| pOpt->preview_buffer = preview_buffer; |
| pOpt->disable_viewfinder = disable_viewfinder; |
| pOpt->add_time_stamp = add_time_stamp; |
| pOpt->use_default_filename = RE_BOOLEAN_FALSE; |
| if (pOpt->path[0] == 0) { |
| pOpt->use_default_filename = RE_BOOLEAN_TRUE; |
| if (getcwd(path, sizeof(path)) == NULL) { |
| LOG_ERROR ("get current path fail\n"); |
| return -1; |
| } |
| } else { |
| strcpy(path, pOpt->path); |
| } |
| |
| return ret; |
| } |
| |
| int main(int argc, char* argv[]) |
| { |
| RecorderEngine* recorder = NULL; |
| REboolean bexit = RE_BOOLEAN_FALSE; |
| REboolean read_input = RE_BOOLEAN_TRUE; |
| REboolean bPause = RE_BOOLEAN_FALSE; |
| REOptions options; |
| char rep[128]; |
| int ret = 0; |
| |
| struct sigaction act; |
| act.sa_handler = signal_handler; |
| sigemptyset(&act.sa_mask); |
| act.sa_flags = 0; |
| sigaction(SIGINT, &act, NULL); |
| |
| memset(&options, 0, sizeof(REOptions)); |
| if (recorder_parse_options(argc,argv,&options)){ |
| LOG_ERROR ("recorder_parse_options fail.\n"); |
| exit (1); |
| } |
| |
| recorder = recorder_engine_create(); |
| if (recorder == NULL) { |
| LOG_ERROR ("RecorderEngineCreate fail.\n"); |
| exit (1); |
| } |
| |
| LOG_INFO ("create recorder successfully\n"); |
| |
| recorder->init((RecorderEngineHandle)recorder); |
| recorder->register_event_handler((RecorderEngineHandle)recorder, recorder, |
| event_handler); |
| |
| if (set_recoder_setting (recorder, &options)) { |
| LOG_ERROR ("set_recoder_setting fail.\n"); |
| goto bail; |
| } |
| |
| if (recorder->prepare((RecorderEngineHandle)recorder)) { |
| LOG_ERROR ("prepare fail.\n"); |
| goto bail; |
| } |
| |
| if (options.list) { |
| list_camera_capabilities(recorder); |
| goto bail; |
| } |
| |
| START_MEDIATIME_INFO_THREAD(media_time_thread, recorder); |
| sem_init(&grecordersem, 0, 0); |
| START_MESSAGE_PROCESS_THREAD(message_process_thread, recorder); |
| |
| while(bexit == RE_BOOLEAN_FALSE) { |
| { |
| if (read_input){ |
| recorder_main_menu(); |
| scanf("%128s", rep); |
| } |
| read_input=RE_BOOLEAN_TRUE; |
| if (quit_flag) { |
| LOG_INFO ("receive Ctrl+c user input.\n"); |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| bexit = RE_BOOLEAN_TRUE; |
| } |
| if(rep[0] == 'r') { |
| if (set_recoder_setting_video (recorder, &options)) { |
| LOG_ERROR ("set_recoder_setting_video fail.\n"); |
| continue; |
| } |
| RECORDER_START; |
| } |
| else if(rep[0] == 'a') { |
| if(bPause != RE_BOOLEAN_TRUE) { |
| RECORDER_PAUSE; |
| bPause = RE_BOOLEAN_TRUE; |
| } |
| else { |
| RECORDER_RESUME; |
| bPause = RE_BOOLEAN_FALSE; |
| } |
| } |
| else if(rep[0] == 's') { |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| } |
| else if(rep[0] == 'n') { |
| if (set_recoder_setting_snap_shot (recorder, &options)) { |
| LOG_ERROR ("set_recoder_setting_snap_shot fail\n"); |
| continue; |
| } |
| RECORDER_TAKE_SNAPSHOT; |
| } |
| else if(rep[0] == 't') |
| { |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_RESET; |
| } |
| else if(rep[0] == 'x') |
| { |
| STOP_SHOW_MEDIATIME_INFO; |
| RECORDER_STOP; |
| bexit = RE_BOOLEAN_TRUE; |
| } |
| else if(rep[0] == '*') { |
| sleep(1); |
| } |
| else if(rep[0] == '#') { |
| sleep(10); |
| } |
| } |
| } |
| |
| STOP_MESSAGE_PROCESS_THREAD(message_process_thread); |
| sem_destroy(&grecordersem); |
| STOP_MEDIATIME_INFO_THREAD(media_time_thread); |
| |
| bail: |
| recorder->close((RecorderEngineHandle)recorder); |
| recorder->delete_it((RecorderEngineHandle)recorder); |
| |
| return 0; |
| } |
| |
| |