MediaObserver Interface#
Playback and recording components process events through a user-defined Observer object derived from MediaObserver.
oasis::MediaObserver is defined in OasisMedia.h as follows:
class MediaObserver : public std::enable_shared_from_this<MediaObserver>
{
public:
MediaObserver();
virtual ~MediaObserver();
//recording or playing started and stopped
virtual void onStarted(void *user_data, const char *file_path);
virtual void onStopped(void *user_data, media_report_reason_t reason, void *details);
//recording a new file
virtual void onFileChanged(void *user_data, const char *new_file_path);
virtual void onFileDeleted(void *user_data, const char *deleted_file_path);
virtual void onError(void *user_data, media_report_reason_t reason, void *details);
//periodic report every 1 second.
virtual void onInfo(void *user_data, MediaInfo *info);
virtual void onInfoEx(void *user_data, MediaInfoEx *info);
//player paused and resumed
virtual void onPaused(void *user_data, MediaInfo *info);
virtual void onResumed(void *user_data, MediaInfo *info);
//event recording started and completed(aborted)
virtual void onEventRecordingStarted(void *user_data, media_report_reason_t reason, const char *file_path);
virtual void onEventRecordingCompleted(void *user_data, media_report_reason_t reason, const char *file_path);
//motion recording started and completed(aborted)
virtual void onMotionRecordingStarted(void *user_data, media_report_reason_t reason, const char *file_path);
virtual void onMotionRecordingCompleted(void *user_data, media_report_reason_t reason, const char *file_path);
virtual void queryNewFilePath(void *user_data, recording_mode_t file_type, bool rear_camera_on, bool sound_on, std::string &file_path);
virtual void onSnapshotCompleted(void *user_data, uint32_t snapshot_id, int32_t camera_id, int error, const std::vector<char> &jpeg_image_data, const struct timeval ×tamp);
};
Note
MediaObserver::onPaused and MediaObserver::onResumed are called during recording file playback.
Header File#
OasisMedia.h
Functions#
startRecording.
startRecording.
General media_report_reason_t constant values are as follows:
| Reason | Constant Value | Meaning | details |
|---|---|---|---|
| kMediaReportGenericError | -1 | General error. | nullptr |
| kMediaReportNoError | 0 | No error has occurred. | nullptr |
For the recording component, media_report_reason_t constant values are as follows:
| Reason | Constant Value | Meaning | details |
|---|---|---|---|
| kRecordingAllFilesRecorded | 201 | Completed all recordings. | nullptr |
| kRecordingErrorNotReady | 400 | Requested to start recording when recording is not ready. | nullptr |
| kRecordingErrorAlreadyStarted | 401 | Recording has already started. | nullptr |
| kRecordingErrorWriterPreparationFailed | 402 | Failed to prepare the recording file. | nullptr |
| kRecordingErrorWriterStartFailed | 403 | Failed to start writing the recording file. | nullptr |
| kRecordingErrorSourceStartFailed | 404 | Failed to start the camera device. | nullptr |
| kRecordingErrorNotPrepared | 405 | State is not prepared (not used). | nullptr |
| kRecordingErrorNotStarted | 406 | State is not started (not used). | nullptr |
| kRecordingErrorDiskAlmostFull | 407 | The disk is almost full (not used). | nullptr |
| kRecordingErrorNoDiskMount | 408 | Not mounted (not used). | nullptr |
| kRecordingErrorFileIO | 409 | File I/O error. | nullptr |
| kRecordingErrorResumeFailed | 410 | Failed to restart recording. | nullptr |
| kRecordingErrorMediaDataTimeout | 411 | Video data has not been generated for a certain period of time. | int32_t camera_id |
| kRecordingErrorIndexTableOverflow | 412 | The index table capacity of the file has been exceeded. | nullptr |
| kRecordingErrorEventWriterPreparationFailed | 430 | Failed to prepare the event recording file. | nullptr |
| kRecordingErrorEventWriterStartFailed | 431 | Failed to start the event recording file. | nullptr |
| kRecordingErrorMotionWriterPreparationFailed | 450 | Failed to prepare the motion recording file. | nullptr |
| kRecordingErrorMotionWriterStartFailed | 451 | Failed to start the motion recording file. | nullptr |
| kRecordingErrorMediaCacheReadErrorBegin | 460 | Initial failure occurred while reading the media cache. | nullptr |
| kRecordingErrorMediaCacheReadErrorEnd | 461 | Failure while reading the media cache has ended. | nullptr |
| kSnapshotErrorTimeout | 600 | Snapshot timeout occurred. | nullptr |
For the playback component, media_report_reason_t constant values are as follows:
| Reason | Constant Value | Meaning | details |
|---|---|---|---|
| kPlayingEndOfFileReached | 200 | Playback of the recording file has ended. | nullptr |
| kPlayingErrorFileNotFound | 500 | Recording file cannot be found. | nullptr |
| kPlayingErrorFileExtNotSupported | 501 | Unsupported recording file extension. | nullptr |
| kPlayingErrorSourceNotReady | 502 | Recording file is not ready. | nullptr |
| kPlayingErrorNoTracks | 503 | No tracks to play. | nullptr |
| kPlayingErrorSoundNotReady | 504 | Audio is not ready. | nullptr |
| kPlayingErrorSoundDecoderNotReady | 505 | Audio decoder is not ready. | nullptr |
| kPlayingErrorVideoRendererNotReady | 506 | Video renderer is not ready. | nullptr |
| kPlayingErrorVideoDecoderNotReady | 507 | Video decoder is not ready. | nullptr |
| kPlayingErrorVideoTrackNotReady | 508 | Video track is not ready. | nullptr |
| kPlayingErrorSubtitleSourceNotReady | 509 | Caption source is not ready. | nullptr |
| kPlayingErrorTextTrackNotReady | 510 | Text track is not ready. | nullptr |
| kPlayingErrorTextDecoderNotReady | 511 | Text decoder is not ready. | nullptr |
| kPlayingErrorTextRendererNotReady | 512 | Text renderer is not ready. | nullptr |
| kPlayingErrorVideoRendererStartFailed | 513 | Cannot start the video renderer. | nullptr |
| kPlayingErrorAudioRendererStartFailed | 514 | Cannot start the audio renderer. | nullptr |
| kPlayingErrorTextRendererStartFailed | 515 | Cannot start the text renderer. | nullptr |
| kPlayingErrorSoundDeviceBusy | 516 | Audio device is busy. | nullptr |
| kPlayingErrorDisplayLayerNotReady | 517 | Display layer is not ready. | nullptr |
| kPlayingErrorZeroDuration | 518 | Playback duration is 0 seconds. | nullptr |
| kPlayingErrorVideoSetupException | 519 | Video initialization error. | nullptr |
| kPlayingErrorAudioSetupException | 520 | Audio initialization error. | nullptr |
| kPlayingErrorAdasNotReady | 521 | ADAS is not ready. | nullptr |
| kPlayingErrorAdasStartFailed | 522 | ADAS start error. | nullptr |
file-duration-secs elapses during recording or the allocated file size is exceeded, recording automatically restarts with a new file. The new file path can be changed when MediaObserver::queryNewFilePath is called.
startRecording.
startRecording.
stopRecording in a separate thread to stop recording, or restart recording after resolving the error problem.
startRecording.
Note
kRecordingErrorMediaCacheReadErrorBegin ~ kRecordingErrorMediaCacheReadErrorEnd occurs when data required for recording cannot be read from the media cache. If recording continues while ignoring this, all data within the range of the time occurrence will be filled with "0" values. In the case of video, a green screen may be visible during playback, and in the case of audio, silence occurs.
report-media-info-ex is set to "0" and the Recorder object is created via createRecorder.
startRecording.
report-media-info-ex is set to "1" and the Recorder object is created via createRecorder.
startRecording.
startRecording.
startRecording.
startRecording.
startRecording.
startRecording.
kRecordingModeNormal(0) or kRecordingModeSniffing(1).
true if the rear camera is also recording.
true if audio is also recording.
normal-folder-path key value applied when creating the recording object or changing parameters.
takeRecordingSnapshot of the recording component.
startRecording.
snapshot_id value received when calling takeRecordingSnapshot.
takeRecordingSnapshot.
kMediaReportNoError(0) if the snapshot is successful.
error is 0. The user can save this data to a file in a separate thread.
Structures#
inSize and outSize, you can verify whether data is being accumulated; if data accumulates, writing performance improvements for the SD card are required.MediaObserver::onInfo event invocation callback function.
true if Sniffing mode. false if normal recording mode.durationUs value.MediaObserver::onInfoEx event invocation callback function. report-media-info-ex must be set to "1" when creating the recording object.
true if Sniffing mode. false if normal recording mode.durationUs value.Example#
Users of the recording component define a class with MediaObserver as a base class, and pass it as a parameter when calling the oasis::startRecording function. Below is an example of creating MyRecordingObserver and passing it to oasis::startRecording.
std::shared_ptr<MyRecordingObserver> recording_observer = std::make_shared<MyRecordingObserver>();
RecorderRef recorder = createRecorder(parameters);
startRecording(recorder, recording_observer, nullptr /*user_data*/);
Below is an example of outputting MediaInfoEx to the console. The dumpInfoEx function is used in other example code resources.
void bytesToString(size_t size, char *size_string)
{
if(size >= 1024*1024) {
sprintf(size_string, "%.2fMB", (double)size/1048576);
} else if(size >= 1024) {
sprintf(size_string, "%.2fKB", (double)size/1024);
} else {
sprintf(size_string, "%dB", size);
}
}
void dumpInfoEx(MediaInfoEx* info)
{
int h, m, s, u;
char normal_qsize[128], event_qsize[128], in_size[128], out_size[128], cache_in_size[128];
char video1_size[128], video2_size[128], meta_size[128], audio_size[128], file_size[128];
parseUsec(info->durationUs, h, m, s, u);
TRACE0("Recording duration \033[33m%02d:%02d:%02d.%06d\033[0m, wq#%d(%d), eq#%d(%d), meq#%d(%d), nohits#%u, mb.avail#%d/%d (free mem %.3fMB, cpu %.2f%%)\r\n", h, m, s, u, info->writerStat.curSamples, info->writerStat.maxSamples, info->timeshiftStat.curSamples, info->timeshiftStat.maxSamples, info->writerStat.motionStat.curSamples, info->writerStat.motionStat.maxSamples, info->mediaCacheStat.nohits_, info->mediaCacheStat.free_buffer_count_, info->mediaCacheStat.total_buffer_count_, (double)oasis::getFreeMemorySize()/1024.0/1024.0, getCPUUsage());
//offs state
bytesToString(info->offsStat.qNormalSize, normal_qsize);
bytesToString(info->offsStat.qEventSize, event_qsize);
bytesToString(info->offsStat.inSize, in_size);
bytesToString(info->offsStat.outSize, out_size);
bytesToString(info->mediaCacheStat.in_size_, cache_in_size);
TRACE0(" cache: during %d msec, in %s\r\n", info->mediaCacheStat.check_duration_, cache_in_size);
TRACE0(" offs: n#%d, e#%d, nz#%s, ez#%s, during %d msec: in %s out %s elapsed %d msec \r\n", info->offsStat.qNormalCount, info->offsStat.qEventCount, normal_qsize, event_qsize, info->offsStat.checkDuration, in_size, out_size, info->offsStat.elapsedSum);
//print recording stat in details
bytesToString(info->writerStat.video1Length, video1_size);
bytesToString(info->writerStat.video2Length, video2_size);
bytesToString(info->writerStat.metaLength, meta_size);
bytesToString(info->writerStat.audioLength, audio_size);
bytesToString(info->writerStat.fileLength, file_size);
TRACE0(" %s: video1 %s, video2 %s, meta %s, audio %s, file %s\n", info->sniffing?"sniffing":"recording", video1_size, video2_size, meta_size, audio_size, file_size);
if(info->writerStat.motionStat.recording) {
bytesToString(info->writerStat.motionStat.video1Length, video1_size);
bytesToString(info->writerStat.motionStat.video2Length, video2_size);
bytesToString(info->writerStat.metaLength, meta_size);
bytesToString(info->writerStat.audioLength, audio_size);
bytesToString(info->writerStat.fileLength, file_size);
TRACE0(" motion: video1 %s, video2 %s, meta %s, audio %s, file %s\n", video1_size, video2_size, meta_size, audio_size, file_size);
}
if(info->timeshiftStat.recording) {
bytesToString(info->timeshiftStat.video1Length, video1_size);
bytesToString(info->timeshiftStat.video2Length, video2_size);
bytesToString(info->timeshiftStat.metaLength, meta_size);
bytesToString(info->timeshiftStat.audioLength, audio_size);
bytesToString(info->timeshiftStat.fileLength, file_size);
TRACE0(" event: video1 %s, video2 %s, meta %s, audio %s, file %s\n", video1_size, video2_size, meta_size, audio_size, file_size);
}
}