sample code - “pull/delete/playback content in RemoteTransferMode”

usage:
  s [1~2(slot)]                             - Select content
  g [0(content),1(thumbnail),2(screennail)] - Get content
  d                                         - Delete content
  ip <192.168.1.2(ip of this PC)>           - set ip of this PC
  p [1(start),2(stop),4(resume),5(pause),6(seek)] - Playback content

  postview <1(enable),0(disable)> <0(legacy),0x8000(file),0x8001(ram)>
  pull
To exit, please enter 'q'.

“Playback content” exports elementary streams to temp.hevc and temp.aac. Please MUX them by using a tool such as ffmpeg.

example:
  ffmpeg -i temp.hevc -i temp.aac -c copy output.mp4
This sample code is included in SimpleCli.
  1// "pull/delete/playback contents in RemoteTransferMode" sample
  2#include <chrono>
  3#include <cstdint>
  4#include <cstdlib>
  5#include <fstream>
  6#include <future>
  7#include <iostream>
  8#include <mutex>
  9#include <sstream>
 10#include <stdexcept>
 11#include <string>
 12#include <thread>
 13#include <vector>
 14
 15#if !defined(__APPLE__)
 16  #if defined(USE_EXPERIMENTAL_FS) // for jetson
 17    #include <experimental/filesystem>
 18    namespace fs = std::experimental::filesystem;
 19  #else
 20    #include <filesystem>
 21    namespace fs = std::filesystem;
 22  #endif
 23#endif
 24
 25#if defined(__APPLE__) || defined(__linux__)
 26  #include <unistd.h>
 27#endif
 28
 29// macro for multibyte character
 30#if defined(_WIN32) || defined(_WIN64)
 31  using CrString = std::wstring;
 32  #define CRSTR(s) L ## s
 33  #define CrCout std::wcout
 34  #define CrPrintf std::wprintf
 35  #define DELIMITER CRSTR("\\")
 36#else
 37  using CrString = std::string;
 38  #define CRSTR(s) s
 39  #define CrCout std::cout
 40  #define CrPrintf std::printf
 41  #define DELIMITER CRSTR("/")
 42#endif
 43
 44
 45#include "CrDeviceProperty.h"
 46#include "CameraRemote_SDK.h"
 47#include "IDeviceCallback.h"
 48#include "CrDebugString.h"   // use CrDebugString.cpp
 49
 50#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
 51#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
 52
 53bool  m_connected = false;
 54CrString m_modelId;
 55int64_t  m_device_handle = 0;
 56uint32_t m_postview_size = 0;
 57CrString m_postview_filename = CRSTR("");
 58
 59std::mutex m_eventPromiseMutex;
 60uint32_t m_setDPCode = 0;
 61std::promise<void>* m_eventPromise = nullptr;
 62void setEventPromise(std::promise<void>* dp)
 63{
 64    std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
 65    m_eventPromise = dp;
 66}
 67
 68std::ofstream* m_fileVideo = nullptr;
 69std::ofstream* m_fileAudio = nullptr;
 70
 71SCRSDK::CrError _getDeviceProperty(int64_t device_handle, uint32_t code, SCRSDK::CrDeviceProperty* devProp)
 72{
 73    std::int32_t nprop = 0;
 74    SCRSDK::CrDeviceProperty* prop_list = nullptr;
 75    SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(device_handle, 1, &code, &prop_list, &nprop);
 76    if(err) GotoError("", err);
 77    if(prop_list && nprop >= 1) {
 78        *devProp = prop_list[0];
 79    }
 80Error:
 81    if(prop_list) SCRSDK::ReleaseDeviceProperties(device_handle, prop_list);
 82    return err;
 83}
 84
 85class DeviceCallback : public SCRSDK::IDeviceCallback
 86{
 87public:
 88    DeviceCallback() {};
 89    ~DeviceCallback() {};
 90
 91    void OnConnected(SCRSDK::DeviceConnectionVersioin version)
 92    {
 93        CrCout << "Connected to " << m_modelId << "\n";
 94        m_connected = true;
 95        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
 96        if(m_eventPromise) {
 97            m_eventPromise->set_value();
 98            m_eventPromise = nullptr;
 99        }
100    }
101
102    void OnError(CrInt32u error)
103    {
104        printf("Connection error:%s\n", CrErrorString(error).c_str());
105        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
106        if(m_eventPromise) {
107            m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
108            m_eventPromise = nullptr;
109        }
110    }
111
112    void OnDisconnected(CrInt32u error)
113    {
114        CrCout << "Disconnected from " << m_modelId << "\n";
115        m_connected = false;
116        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
117        if(m_eventPromise) {
118            m_eventPromise->set_value();
119            m_eventPromise = nullptr;
120        }
121    }
122
123    void OnCompleteDownload(CrChar* filename, CrInt32u type )
124    {
125        CrCout << "OnCompleteDownload:" << filename << "\n";
126    }
127
128    void OnNotifyPostViewImage(CrChar* filename, CrInt32u size)
129    {
130        CrCout << "OnNotifyPostViewImage:" << filename << "," << size << "\n";
131        m_postview_size = size;
132        m_postview_filename = filename;
133    }
134
135    void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
136    {
137        std::cout << "OnNotifyContentsTransfer:" << CrErrorString(notify) << "\n";
138    }
139    
140    void OnNotifyRemoteTransferResult(CrInt32u notify, CrInt32u per, CrChar* filename)
141    {
142        std::cout << "OnNotifyRemoteTransferResult:" << CrErrorString(notify) << "\n";
143        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
144        switch(notify) {
145        case SCRSDK::CrNotify_RemoteTransfer_Result_OK:
146            CrCout << filename << "\n";
147            if(m_eventPromise) {
148                m_eventPromise->set_value();
149                m_eventPromise = nullptr;
150            }
151            break;
152        case SCRSDK::CrNotify_RemoteTransfer_Result_NG:
153        case SCRSDK::CrNotify_RemoteTransfer_Result_DeviceBusy:
154            if(m_eventPromise) {
155                m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
156                m_eventPromise = nullptr;
157            }
158            break;
159        }
160    }
161
162    void OnNotifyRemoteTransferResult(CrInt32u notify, CrInt32u per, CrInt8u* data, CrInt64u size)
163    {
164        std::cout << "OnNotifyRemoteTransferResult xx:" << CrErrorString(notify) << "\n";
165        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
166        if(m_eventPromise) {
167            m_eventPromise->set_value();
168            m_eventPromise = nullptr;
169        }
170    }
171
172    void OnNotifyRemoteTransferContentsListChanged(CrInt32u notify, CrInt32u slotNumber, CrInt32u addSize)
173    {
174        std::cout << "OnNotifyRemoteTransferContentsListChanged:" << CrErrorString(notify) << "\n";
175    }
176
177    void OnReceivePlaybackData(CrInt8u mediaType, CrInt32 dataSize, CrInt8u* data, CrInt64 pts, CrInt64 dts, CrInt32 param1, CrInt32 param2)
178    {
179    //  std::cout << "OnReceivePlaybackData:\n";
180        switch(mediaType) {
181        case SCRSDK::CrMoviePlaybackDataType_Video:
182            if(m_fileVideo) m_fileVideo->write((char*)data, dataSize);
183            break;
184        case SCRSDK::CrMoviePlaybackDataType_Audio:
185            if(m_fileAudio) m_fileAudio->write((char*)data, dataSize);
186            break;
187        }
188    }
189    void OnReceivePlaybackTimeCode(CrInt32u timeCode)
190    {
191    //  printf("OnReceivePlaybackTimeCode:%d\n", timeCode);
192    }
193
194    void OnWarning(CrInt32u warning)
195    {
196        if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
197            CrCout << "Reconnecting to " << m_modelId << "\n";
198            return;
199        }
200        std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
201        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
202        switch(warning) {
203        case SCRSDK::CrNotify_Playback_Result_StopComplete:
204            if(m_fileVideo) {
205                m_fileVideo->close();
206                m_fileVideo = nullptr;
207            }
208            if(m_fileAudio) {
209                m_fileAudio->close();
210                m_fileAudio = nullptr;
211            }
212            [[fallthrough]];
213        case SCRSDK::CrNotify_Playback_StatusChanged:
214            if(m_eventPromise) {
215                m_eventPromise->set_value();
216                m_eventPromise = nullptr;
217            }
218            break;
219
220        case SCRSDK::CrNotify_Playback_Result_NormalTermination:
221            SCRSDK::ControlMoviePlayback(m_device_handle, SCRSDK::CrMoviePlaybackControlType_Stop, 0);
222            break;
223
224        case SCRSDK::CrWarning_Playback_Result_Invalid:
225        case SCRSDK::CrWarning_Playback_Result_CameraOperateTermination:
226        case SCRSDK::CrWarning_Playback_Result_SystemError:
227        case SCRSDK::CrWarning_Playback_Result_HighTemperature:
228        case SCRSDK::CrWarning_Playback_Result_MediaRemoval:
229        case SCRSDK::CrWarning_Playback_Result_ContentsError:
230        case SCRSDK::CrWarning_Playback_Result_KeepAliveTimeout:
231        case SCRSDK::CrWarning_Playback_Result_Start_Fail:
232        case SCRSDK::CrWarning_Playback_Result_Stop_Fail:
233        case SCRSDK::CrWarning_Playback_Result_Play_Fail:
234        case SCRSDK::CrWarning_Playback_Result_Pause_Fail:
235            if(m_eventPromise) {
236                m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
237                m_eventPromise = nullptr;
238            }
239            break;
240/*
241        case SCRSDK::CrNotify_Playback_Result_PlaybackInfo_Success:
242        case SCRSDK::CrWarning_Playback_Result_PlaybackInfo_Error:
243*/
244        }
245    }
246
247    void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3)
248    {
249        std::cout << "OnWarningExt:" << CrWarningExtString(warning, param1, param2, param3).c_str() << "\n";
250        if(warning == SCRSDK::CrWarningExt_DeleteContent) {
251            std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
252            switch(param1) {
253            case SCRSDK::CrWarningExtParam_DeleteContentResult_OK:
254                if(m_eventPromise) {
255                    m_eventPromise->set_value();
256                    m_eventPromise = nullptr;
257                }
258                break;
259            default:
260                if(m_eventPromise) {
261                    m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
262                    m_eventPromise = nullptr;
263                }
264                break;
265            }
266        }
267    }
268    void OnLvPropertyChanged() {}
269    void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
270    void OnPropertyChanged() {}
271    void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes)
272    {
273        for(uint32_t i = 0; i < num; ++i) {
274            if(codes[i] == SCRSDK::CrDeviceProperty_PullPostViewImageStatus) {
275                SCRSDK::CrDeviceProperty devProp;
276                SCRSDK::CrError err = _getDeviceProperty(m_device_handle, SCRSDK::CrDeviceProperty_PullPostViewImageStatus, &devProp);
277                if(!err) {
278                    std::cout << "OnPropertyChangedCodes:PullPostViewImageStatus=" << (devProp.GetCurrentValue() ? "Exists" : "Not Exists") << "\n";
279                }
280            }
281        }
282    }
283};
284
285CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
286{
287    CrString id;
288    if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
289        id = CrString(objInfo->GetMACAddressChar());
290    } else {
291        id = CrString((CrChar*)objInfo->GetId());
292    }
293    return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
294}
295
296SCRSDK::CrError _getIdPassword(SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
297{
298    char fpBuff[128] = {0};
299    CrInt32u fpLen = 0;
300    SCRSDK::CrError err = SCRSDK::GetFingerprint(objInfo, fpBuff, &fpLen);
301    if(err) GotoError("", err);
302    fingerprint = std::string(fpBuff, fpLen);
303
304    std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
305    std::cout << "id:";       std::getline(std::cin, userId);
306    std::cout << "password:"; std::getline(std::cin, userPassword);
307    return 0;
308Error:
309    return err;
310}
311
312SCRSDK::CrError _shooting(int64_t device_handle)
313{
314    SCRSDK::CrError err = 0;
315
316    err = SCRSDK::SendCommand(device_handle, SCRSDK::CrCommandId_Release, SCRSDK::CrCommandParam_Down); if (err) GotoError("", err);
317    std::this_thread::sleep_for(std::chrono::milliseconds(35));
318    err = SCRSDK::SendCommand(device_handle, SCRSDK::CrCommandId_Release, SCRSDK::CrCommandParam_Up); if (err) GotoError("", err);
319
320    std::cout << "OK\n";
321Error:
322    return err;
323}
324
325void _showContentsInfo(SCRSDK::CrContentsInfo& contentsInfo)
326{
327    std::cout << "\n";
328    std::cout << "[ContentsInfo]\n";
329    printf("contentType = %d\n", contentsInfo.contentType);
330    printf("contentId = %u\n", contentsInfo.contentId);
331    printf("dirNumber = %u\n", contentsInfo.dirNumber);
332    printf("fileNumber = %u\n", contentsInfo.fileNumber);
333    printf("groupType = %d\n", contentsInfo.groupType);
334    printf("representative = %u\n", contentsInfo.representative);
335    printf("creationDatetimeUTC = %04d/%02d/%02d %02d:%02d:%02d.%03d\n",
336            contentsInfo.creationDatetimeUTC.year, 
337            contentsInfo.creationDatetimeUTC.month, 
338            contentsInfo.creationDatetimeUTC.day,
339            contentsInfo.creationDatetimeUTC.hour, 
340            contentsInfo.creationDatetimeUTC.minute,
341            contentsInfo.creationDatetimeUTC.sec, 
342            contentsInfo.creationDatetimeUTC.msec);
343    printf("modificationDatetimeUTC = %04d/%02d/%02d %02d:%02d:%02d.%03d\n",
344            contentsInfo.modificationDatetimeUTC.year, 
345            contentsInfo.modificationDatetimeUTC.month, 
346            contentsInfo.modificationDatetimeUTC.day,
347            contentsInfo.modificationDatetimeUTC.hour, 
348            contentsInfo.modificationDatetimeUTC.minute,
349            contentsInfo.modificationDatetimeUTC.sec, 
350            contentsInfo.modificationDatetimeUTC.msec);
351    printf("creationDatetimeLocaltime = %04d/%02d/%02d %02d:%02d:%02d.%03d\n",
352            contentsInfo.creationDatetimeLocaltime.year, 
353            contentsInfo.creationDatetimeLocaltime.month, 
354            contentsInfo.creationDatetimeLocaltime.day,
355            contentsInfo.creationDatetimeLocaltime.hour, 
356            contentsInfo.creationDatetimeLocaltime.minute,
357            contentsInfo.creationDatetimeLocaltime.sec, 
358            contentsInfo.creationDatetimeLocaltime.msec);
359    printf("modificationDatetimeLocaltime = %04d/%02d/%02d %02d:%02d:%02d.%03d\n",
360            contentsInfo.modificationDatetimeLocaltime.year, 
361            contentsInfo.modificationDatetimeLocaltime.month, 
362            contentsInfo.modificationDatetimeLocaltime.day,
363            contentsInfo.modificationDatetimeLocaltime.hour, 
364            contentsInfo.modificationDatetimeLocaltime.minute,
365            contentsInfo.modificationDatetimeLocaltime.sec, 
366            contentsInfo.modificationDatetimeLocaltime.msec);
367    printf("rating = %d\n", contentsInfo.rating);
368    printf("protectionStatus = %u\n", contentsInfo.protectionStatus);
369    printf("dummyContent = %u\n", contentsInfo.dummyContent);
370    printf("shotMarkNum = %u\n", contentsInfo.shotMarkNum);
371    for(CrInt32u i = 0; i < contentsInfo.shotMarkNum; i++) {
372        printf("No:%d, shotMark = %u\n",(i+1), contentsInfo.shotMark[i]);
373    }
374    printf("filesNum = %u\n", contentsInfo.filesNum);
375}
376
377void _showContentsFile(SCRSDK::CrContentsFile& contentsFile)
378{
379    printf("fileId = %u\n", contentsFile.fileId);
380    printf("filePathLength = %u\n", contentsFile.filePathLength);
381    if( contentsFile.filePathLength > 0 ) {
382        printf("filePath = %s\n", contentsFile.filePath);
383    }
384    printf("fileFormat = %u\n", contentsFile.fileFormat);
385    printf("fileSize = %d\n", (int)contentsFile.fileSize);
386    std::cout << "umid = 0x";
387    for(int j = 0; j < sizeof(contentsFile.umid); j++) {
388        printf("%02x", contentsFile.umid[j]);
389    }
390    std::cout << "\n";
391
392    printf("isImageParamExsist = %u\n", contentsFile.isImageParamExsist);
393    if( contentsFile.isImageParamExsist == true ) {
394        printf("imagePixWidth = %u\n", contentsFile.imageParam.imagePixWidth);
395        printf("imagePixHeight = %u\n", contentsFile.imageParam.imagePixHeight);
396    }
397
398    printf("isVideoParamExsist = %u\n", contentsFile.isVideoParamExsist);
399    if( contentsFile.isVideoParamExsist == true ) {
400        printf("startTimeCode = %u\n", contentsFile.videoParam.startTimeCode);
401        printf("endTimeCode = %u\n", contentsFile.videoParam.endTimeCode);
402        printf("videoCodec = %d\n", contentsFile.videoParam.videoCodec);
403        printf("proxyStatus = %u\n", contentsFile.videoParam.proxyStatus);
404        printf("gopStructure = %d\n", contentsFile.videoParam.gopStructure);
405        printf("width = %u\n", contentsFile.videoParam.width);
406        printf("height = %u\n", contentsFile.videoParam.height);
407        printf("aspectRatio = %d\n", contentsFile.videoParam.aspectRatio);
408        printf("colorFormat = %d\n", contentsFile.videoParam.colorFormat);
409        printf("imageBitDepth = %u\n", contentsFile.videoParam.imageBitDepth);
410        printf("framesPerThousandSeconds = %u\n", contentsFile.videoParam.framesPerThousandSeconds);
411        printf("scanType = %d\n", contentsFile.videoParam.scanType);
412        printf("bitrateMbps = %u\n", contentsFile.videoParam.bitrateMbps);
413        printf("imageFramesPerThousandSeconds = %u\n", contentsFile.videoParam.imageFramesPerThousandSeconds);
414        printf("profileIndication = %d\n", contentsFile.videoParam.profileIndication);
415        printf("profileLevel = %u\n", contentsFile.videoParam.profileLevel);
416        printf("rdd18metaCaptureGammaEquation = %d\n", contentsFile.videoParam.rdd18metaCaptureGammaEquation);
417        printf("rdd18metaColorPrimaries = %d\n", contentsFile.videoParam.rdd18metaColorPrimaries);
418        printf("rdd18metaCodingEquations = %d\n", contentsFile.videoParam.rdd18metaCodingEquations);
419    }
420
421    printf("isAudioParamExsist = %u\n", contentsFile.isAudioParamExsist);
422    if( contentsFile.isAudioParamExsist == true ) {
423        printf("audioCodec = %d\n", contentsFile.audioParam.audioCodec);
424        printf("audioBitDepth = %u\n", contentsFile.audioParam.audioBitDepth);
425        printf("samplingRate = %u\n", contentsFile.audioParam.samplingRate);
426        printf("numberOfChannels = %d\n", contentsFile.audioParam.numberOfChannels);
427    }
428    std::cout << "\n";
429}
430
431SCRSDK::CrError _selectContent(int64_t device_handle, SCRSDK::CrSlotNumber slotNumber, CrInt32u& contentId, CrInt32u& fileId)
432{
433    int result = SCRSDK::CrError_Generic_Unknown;
434    SCRSDK::CrError err = SCRSDK::CrError_None;
435    int index = 0;
436
437    SCRSDK::CrCaptureDate* m_captureDateList = nullptr;
438    SCRSDK::CrContentsInfo* m_contentsInfoList = nullptr;
439    std::string inputLine;
440    CrInt32u outNums = 0;
441
442    SCRSDK::CrContentsInfo contentsInfo;
443    SCRSDK::CrContentsFile contentsFile;
444
445    // select date
446    err = SCRSDK::GetRemoteTransferCapturedDateList(device_handle, slotNumber, &m_captureDateList, &outNums);
447    if(err || outNums == 0) GotoError("", err);
448
449    for(CrInt32u i = 0; i < outNums; i++) {
450        printf("[%d] %04d/%02d/%02d\n",(int)i, m_captureDateList[i].year, m_captureDateList[i].month, m_captureDateList[i].day);
451    }
452
453    std::cout << "date(0~ ):"; std::getline(std::cin, inputLine);
454    try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
455    if(index < 0 || index >= (int)outNums) GotoError("", 0);
456
457    // select content
458    err = SCRSDK::GetRemoteTransferContentsInfoList(device_handle, slotNumber, SCRSDK::CrGetContentsInfoListType_Range_Day,
459                                                    &m_captureDateList[index], /*maxNums*/0,
460                                                    &m_contentsInfoList, &outNums);
461    if(err) GotoError("", err);
462
463    for(CrInt32u i = 0;i < outNums; i++) {
464        printf("[%d] %04d/%02d/%02d %02d:%02d:%02d, FileName:%s\n", i,
465            m_contentsInfoList[i].creationDatetimeLocaltime.year,
466            m_contentsInfoList[i].creationDatetimeLocaltime.month,
467            m_contentsInfoList[i].creationDatetimeLocaltime.day,
468            m_contentsInfoList[i].creationDatetimeLocaltime.hour,
469            m_contentsInfoList[i].creationDatetimeLocaltime.minute,
470            m_contentsInfoList[i].creationDatetimeLocaltime.sec,
471            m_contentsInfoList[i].files[0].filePath);
472    }
473
474    std::cout << "index(0~ ):"; std::getline(std::cin, inputLine);
475    try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
476    if(index < 0 || index >= (int)outNums) GotoError("", 0);
477
478    contentsInfo = m_contentsInfoList[index];
479
480    // select file
481    if (contentsInfo.filesNum > 1) {
482        for(CrInt32u i = 0; i < contentsInfo.filesNum; i++) {
483            printf("[%d] FileId:%d, FileName:%s\n", i,
484                contentsInfo.files[i].fileId,
485                contentsInfo.files[i].filePath);
486        }
487        std::cout << "index(0~ ):"; std::getline(std::cin, inputLine);
488        try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
489        if(index < 0 || index >= (int)contentsInfo.filesNum) GotoError("", 0);
490    } else {
491        index = 0;
492    }
493    contentsFile = contentsInfo.files[index];
494
495    _showContentsInfo(contentsInfo);
496    _showContentsFile(contentsFile);
497
498    contentId = contentsInfo.contentId;
499    fileId = contentsFile.fileId;
500
501    result = 0;
502Error:
503    if (m_contentsInfoList) SCRSDK::ReleaseRemoteTransferContentsInfoList(device_handle, m_contentsInfoList);
504    if (m_captureDateList) SCRSDK::ReleaseRemoteTransferCapturedDateList(device_handle, m_captureDateList);
505    return result;
506}
507
508SCRSDK::CrError _controlMoviePlayback(int64_t device_handle, SCRSDK::CrMoviePlaybackControlType operation)
509{
510    SCRSDK::CrError err = SCRSDK::CrError_None;
511/*
512    CrMoviePlaybackControlType_Start = 0x00000001,
513    CrMoviePlaybackControlType_Stop,
514    CrMoviePlaybackControlType_Play = 0x00000004,
515    CrMoviePlaybackControlType_Pause,
516    CrMoviePlaybackControlType_Seek,
517*/
518    std::promise<void> eventPromise;
519    std::future<void> eventFuture = eventPromise.get_future();
520    std::future_status status;
521
522    setEventPromise(&eventPromise);
523    err = SCRSDK::ControlMoviePlayback(device_handle, operation, 0);
524    if(err) GotoError("", err);
525
526    status = eventFuture.wait_for(std::chrono::milliseconds(10000));
527    if(status != std::future_status::ready) GotoError("timeout",0);
528    try{
529        eventFuture.get();
530    } catch(const std::exception&) GotoError("", 0);
531    return 0;
532Error:
533    setEventPromise(nullptr);
534    return SCRSDK::CrError_Generic_Unknown;
535}
536
537SCRSDK::CrError _playbackStart(int64_t device_handle, SCRSDK::CrSlotNumber slotNumber, CrInt32u contentId, CrInt32u fileId, std::string ipAddress, CrString path)
538{
539    SCRSDK::CrError err = SCRSDK::CrError_None;
540    SCRSDK::CrMoviePlaybackSetting setting;
541
542    if(contentId == 0) {
543        std::cout << "select content\n";
544        return SCRSDK::CrError_Generic_Unknown;
545    }
546    if(ipAddress == "") {
547        std::cout << "enter ip address of this pc\n";
548        return SCRSDK::CrError_Generic_Unknown;
549    }
550
551    setting.slotId = slotNumber;
552    setting.contentsId = contentId;
553    setting.fileId = fileId;
554    setting.SetIpAddress(ipAddress.c_str());
555
556    err = SCRSDK::SetMoviePlaybackSetting(device_handle, &setting, 1);
557    if(err) GotoError("", err);
558
559    err = _controlMoviePlayback(device_handle, SCRSDK::CrMoviePlaybackControlType_Start);
560    if(err) goto Error;
561
562    m_fileVideo = new std::ofstream(path + CrString(DELIMITER CRSTR("temp.hevc")), std::ios::out | std::ios::binary);
563    if (m_fileVideo->bad()) GotoError("", 0);
564
565    m_fileAudio = new std::ofstream(path + CrString(DELIMITER CRSTR("temp.aac")), std::ios::out | std::ios::binary);
566    if (m_fileAudio->bad()) GotoError("", 0);
567    CrCout << "write files to:" << path.data() << "\n" "Please convert files with \"ffmpeg -i temp.hevc -i temp.aac -c copy output.mp4\"\n";
568
569    err = _controlMoviePlayback(device_handle, SCRSDK::CrMoviePlaybackControlType_Play);
570    if(err) goto Error;
571    return 0;
572Error:
573    if(m_fileVideo) {
574        m_fileVideo->close();
575        m_fileVideo = nullptr;
576    }
577    if(m_fileAudio) {
578        m_fileAudio->close();
579        m_fileAudio = nullptr;
580    }
581    return SCRSDK::CrError_Generic_Unknown;
582}
583
584std::vector<std::string> _split(std::string inputLine, char delimiter)
585{
586    std::vector<std::string> strArray;
587    if (inputLine.empty()) return strArray;
588
589    std::string tmp;
590    std::stringstream ss{inputLine};
591    while (getline(ss, tmp, delimiter)) {
592        strArray.push_back(tmp);
593    }
594    return strArray;
595}
596
597int64_t _stoll(std::string inputLine)
598{
599    int64_t data = 0;
600    if(inputLine.empty()) throw std::runtime_error("error");
601    try {
602        if (inputLine.compare(0, 2, "0x") == 0 || inputLine.compare(0, 2, "0X") == 0) {
603            data = std::stoull(inputLine.substr(2), nullptr, 16);
604        } else {
605            data = std::stoll(inputLine, nullptr, 10);
606        }
607    } catch(const std::exception& ex) {
608        throw ex;
609    }
610    return data;
611}
612
613int main(void)
614{
615    int result = -1;
616    SCRSDK::CrError err = SCRSDK::CrError_None;
617    SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
618    SCRSDK::ICrCameraObjectInfo* objInfo = nullptr;
619    DeviceCallback deviceCallback;
620    std::string inputLine;
621
622  #if defined(__APPLE__)
623    #define MAC_MAX_PATH 255
624    char pathBuf[MAC_MAX_PATH] = {0};
625    if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
626    CrString path = pathBuf;
627  #else
628    CrString path = fs::current_path().native();
629  #endif
630
631    bool boolRet = SCRSDK::Init();
632    if(!boolRet) GotoError("", 0);
633
634    // enumeration
635    {
636        uint32_t count = 0;
637        uint32_t index = 1;
638
639        err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
640        if(err || !enumCameraObjectInfo) GotoError("no camera", err);
641
642        count = enumCameraObjectInfo->GetCount();
643        if(count >= 2) {
644            for (uint32_t i = 0; i < count; ++i) {
645                auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
646                CrCout << '[' << i + 1 << "] " << _getModelId(info) << "\n";
647            }
648
649            std::cout << "select camera:"; std::getline(std::cin, inputLine);
650            try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
651            if(index < 1 || index > count) GotoError("", 0);
652        }
653        objInfo = (SCRSDK::ICrCameraObjectInfo*)enumCameraObjectInfo->GetCameraObjectInfo(index - 1);
654        m_modelId = _getModelId(objInfo);
655    }
656
657    // connect
658    {
659        std::string  fingerprint = "";
660        std::string  userId = "";
661        std::string  userPassword = "";
662        std::promise<void> eventPromise;
663        std::future<void> eventFuture = eventPromise.get_future();
664
665        if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
666            err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
667        }
668
669        setEventPromise(&eventPromise);
670        err = SCRSDK::Connect(objInfo, &deviceCallback, &m_device_handle,
671            SCRSDK::CrSdkControlMode_RemoteTransfer,
672            SCRSDK::CrReconnecting_ON,
673            userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
674        if(err) GotoError("", err);
675
676    //  std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
677    //  if(status != std::future_status::ready) GotoError("timeout",0);
678        try{
679            eventFuture.get();
680        } catch(const std::exception&) GotoError("", 0);
681    }
682
683    // set work directory
684    {
685        CrCout << "path=" << path.data() << "\n";
686        err = SCRSDK::SetSaveInfo(m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
687        if(err) GotoError("", err);
688    }
689
690    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
691
692    #define _printUsage() { \
693        std::cout << "usage:\n"; \
694        std::cout << "  s [1~2(slot)]                             - Select content\n"; \
695        std::cout << "  g [0(content),1(thumbnail),2(screennail)] - Get content\n"; \
696        std::cout << "  d                                         - Delete content\n"; \
697        std::cout << "  ip <192.168.1.2(ip of this PC)>           - set ip of this PC\n"; \
698        std::cout << "  p [1(start),2(stop),4(resume),5(pause),6(seek)] - Playback content\n"; \
699        std::cout << "\n"; \
700        std::cout << "  shot                                      - Shutter Release\n"; \
701        std::cout << "  postview <1(enable),0(disable)> <0(legacy),0x8000(file),0x8001(ram)>\n"; \
702        std::cout << "  pull\n"; \
703        std::cout << "To exit, please enter 'q'.\n"; \
704    }
705    _printUsage();
706
707    {
708        SCRSDK::CrSlotNumber slotNumber = SCRSDK::CrSlotNumber_Slot1;
709        CrInt32u contentId = 0;
710        CrInt32u fileId = 0;
711        std::string ipAddress;
712
713        while(1) {
714            std::string inputLine;
715            std::cout << "cmd:"; std::getline(std::cin, inputLine);
716            std::vector<std::string> args = _split(inputLine, ' ');
717            int args2 = 0;
718            if(args.size() >= 2 && args[0] != "ip") {
719                try { args2 = stol(args[1]); } catch(const std::exception&) { GotoError("", 0); }
720            }
721
722            if(args.size() == 0) {
723                
724            } else if(args[0] == "s") {  // select content
725                if(args2 != 0) slotNumber = (SCRSDK::CrSlotNumber)args2;
726                err = _selectContent(m_device_handle, slotNumber, contentId, fileId);
727                //if(err) goto Error;
728
729            } else if(args[0] == "d" || args[0] == "g") { // delete/get content
730                std::promise<void> eventPromise;
731                std::future<void> eventFuture = eventPromise.get_future();
732
733                if(contentId == 0) {
734                    std::cout << "select media\n";
735                    continue;
736                }
737
738                #if defined(__linux__)
739                  #define DivisionSize 0x1000000 // 16MB (16 * 1024 * 1024)
740                #else
741                  #define DivisionSize 0x5000000 // 80MB (80 * 1024 * 1024)
742                #endif
743                setEventPromise(&eventPromise);
744                if(args[0] == "d") {
745                    err = SCRSDK::DeleteRemoteTransferContentsFile(
746                                    m_device_handle, slotNumber, contentId);
747                    contentId = 0;
748                } else if(args2 == 0) {
749                    err = SCRSDK::GetRemoteTransferContentsDataFile(
750                                    m_device_handle, slotNumber, contentId, fileId,
751                                    DivisionSize, nullptr, nullptr);
752                } else if(args2 == 1) {
753                    err = SCRSDK::GetRemoteTransferContentsCompressedDataFile(
754                                    m_device_handle, slotNumber, contentId, fileId,
755                                    SCRSDK::CrGetContentsCompressedDataType_Thumbnail, nullptr, nullptr);
756                } else if(args2 == 2) {
757                    err = SCRSDK::GetRemoteTransferContentsCompressedDataFile(
758                                    m_device_handle, slotNumber, contentId, fileId,
759                                    SCRSDK::CrGetContentsCompressedDataType_Screennail, nullptr, nullptr);
760                } else {
761                    GotoError("", 0);
762                }
763                if(err) GotoError("", err);
764
765                try{
766                    eventFuture.get();
767                } catch(const std::exception&) GotoError("", 0);
768                std::cout << "OK\n";
769
770            } else if(args[0] == "ip") {
771                if(args.size() >= 2) {
772                    ipAddress = args[1];
773                }
774            } else if(args[0] == "p") { // playback content
775                if(args2 == 0 || args2 == 1) { /*start*/
776                    err = _playbackStart(m_device_handle, slotNumber, contentId, fileId, ipAddress, path);
777                } else {
778                    err = _controlMoviePlayback(m_device_handle, (SCRSDK::CrMoviePlaybackControlType)args2);
779                }
780                //if(err) goto Error;
781
782            } else if (args[0] == "shot" || args[0] == "SHOT") { // Shutter Release
783                err = _shooting(m_device_handle);
784                //if (err) goto Error;
785
786                // ffmpeg -i temp.hevc -i temp.aac -c copy output.mp4
787            } else if(args[0] == "postview" && args.size() >= 3) {
788                int data = 0;
789                try { data = (int)_stoll(args[1]); } catch(const std::exception&) { GotoError("", 0); }
790                err = SCRSDK::SetDeviceSetting(m_device_handle, SCRSDK::Setting_Key_EnablePostView, data);
791                if(err) GotoError("", err)
792
793                try { data = (int)_stoll(args[2]); } catch(const std::exception&) { GotoError("", 0); }
794                err = SCRSDK::SetDeviceSetting(m_device_handle, SCRSDK::Setting_Key_PostViewTransferringType, data);
795                if(err) GotoError("", err)
796            } else if(args[0] == "pull") {
797                if(m_postview_size) {
798                    uint32_t size = m_postview_size;
799                    CrString filename = path + DELIMITER + m_postview_filename;
800
801                    uint8_t* buf = (uint8_t*)malloc(size);
802                    if(!buf) GotoError("", 0);
803
804                    m_postview_size = 0;
805                    m_postview_filename = CRSTR("");
806
807                    err = SCRSDK::PullPostViewImage(m_device_handle, buf, size);
808                    if(err) GotoError("", err)
809
810                    std::ofstream file(filename, std::ios::out | std::ios::binary);
811                    if (file.bad()) GotoError("", 0);
812                    file.write((char*)buf, size);
813                    file.close();
814                    CrCout << filename.data() << "," << size << "\n";
815
816                    free(buf);
817                }
818            } else if(args[0] == "q" || args[0] == "Q") {
819                break;
820            } else {
821                _printUsage();
822            }
823        }
824    }
825    result = 0;
826Error:
827    if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
828
829    if(m_connected) {
830        std::promise<void> eventPromise;
831        std::future<void> eventFuture = eventPromise.get_future();
832        setEventPromise(&eventPromise);
833        SCRSDK::Disconnect(m_device_handle);
834        eventFuture.wait_for(std::chrono::milliseconds(3000));
835    }
836    if(m_device_handle) SCRSDK::ReleaseDevice(m_device_handle);
837    SCRSDK::Release();
838
839    if(m_fileVideo) {
840        m_fileVideo->close();
841        m_fileVideo = nullptr;
842    }
843    if(m_fileAudio) {
844        m_fileAudio->close();
845        m_fileAudio = nullptr;
846    }
847
848    return result;
849}