static int cps_get_position(void* data, int64_t* position) { ClipSource* clipSource = (ClipSource*)data; if (clipSource->duration >= 0) { int64_t targetPosition; if (!msc_get_position(clipSource->targetSource, &targetPosition)) { return 0; } *position = targetPosition - clipSource->start; *position = (*position > clipSource->duration) ? clipSource->duration : *position; *position = (*position < 0) ? 0 : *position; return 1; } else if (clipSource->start > 0) { int64_t targetPosition; if (!msc_get_position(clipSource->targetSource, &targetPosition)) { return 0; } *position = targetPosition - clipSource->start; *position = (*position < 0) ? 0 : *position; return 1; } return msc_get_position(clipSource->targetSource, position); }
static int cps_read_frame(void* data, const FrameInfo* frameInfo, MediaSourceListener* listener) { ClipSource* clipSource = (ClipSource*)data; if (clipSource->duration >= 0) { /* check the position is within the clip boundaries */ int64_t position; if (!msc_get_position(clipSource->targetSource, &position)) { return -1; } if (position < clipSource->start || position >= clipSource->start + clipSource->duration) { return -1; } } else if (clipSource->start > 0) { /* check the position is within the clip boundaries */ int64_t position; if (!msc_get_position(clipSource->targetSource, &position)) { return -1; } if (position < clipSource->start) { return -1; } } return msc_read_frame(clipSource->targetSource, frameInfo, listener); }
static int cps_seek_timecode(void* data, const Timecode* timecode, TimecodeType type, TimecodeSubType subType) { ClipSource* clipSource = (ClipSource*)data; int64_t originalPosition = -1; int64_t position; /* get position so we can recover is seek is outside the clip boundaries */ if (!msc_get_position(clipSource->targetSource, &originalPosition)) { originalPosition = -1; /* unknown */ } int result = msc_seek_timecode(clipSource->targetSource, timecode, type, subType); if (originalPosition < 0 || result != 0) { return result; } /* check the seek is within the clip boundaries */ if (!msc_get_position(clipSource->targetSource, &position)) { /* TODO: what now? */ /* assume outside - go back to original position */ msc_seek(clipSource->targetSource, originalPosition); return -1; } if (clipSource->duration >= 0) { if (position < clipSource->start || position > clipSource->start + clipSource->duration) { /* outside - go back to original position */ msc_seek(clipSource->targetSource, originalPosition); return -1; } } else if (clipSource->start > 0) { if (position < clipSource->start) { /* outside - go back to original position */ msc_seek(clipSource->targetSource, originalPosition); return -1; } } return result; }
static int sync_sources(MultipleMediaSources* multSource) { MediaSourceElement* ele = &multSource->sources; int64_t position; int syncResult = 0; while (ele != NULL && ele->source != NULL) { if (!SOURCE_IS_DISABLED(ele)) { if (!msc_get_position(ele->source, &position)) { syncResult = -1; break; } if (position != multSource->syncPosition) { /* seek back to the sync position */ syncResult = msc_seek(ele->source, multSource->syncPosition); if (syncResult != 0) { break; } } } ele = ele->next; } return syncResult; }
static int cps_eof(void* data) { ClipSource* clipSource = (ClipSource*)data; if (clipSource->duration >= 0) { if (msc_eof(clipSource->targetSource)) { return 1; } int64_t position; if (!msc_get_position(clipSource->targetSource, &position)) { return 0; } return position >= clipSource->start + clipSource->duration; } return msc_eof(clipSource->targetSource); }
static int mls_seek_timecode(void* data, const Timecode* timecode, TimecodeType type, TimecodeSubType subType) { MultipleMediaSources* multSource = (MultipleMediaSources*)data; MediaSourceElement* ele = &multSource->sources; int seekResult = 0; int haveATimedOutResult = 0; int failed = 0; MediaSourceElement* passedEle = NULL; int64_t position; int syncResult; /* make sure the sources are in sync */ if ((syncResult = sync_sources(multSource)) != 0) { return syncResult; } /* find the source that supports and successfully seeks to the timecode */ while (ele != NULL && ele->source != NULL) { if (!SOURCE_IS_DISABLED(ele)) { seekResult = msc_seek_timecode(ele->source, timecode, type, subType); if (seekResult == 0) { passedEle = ele; if (!msc_get_position(ele->source, &position)) { ml_log_error("Failed to get position at seek to timecode\n"); return -1; } break; } else if (seekResult == -2) { haveATimedOutResult = 1; } } ele = ele->next; } if (passedEle == NULL) { /* none of the sources could be seeked to the timecode */ if (haveATimedOutResult) { /* assume that the timed out source could have seeked to the timecode */ return -2; } return -1; } /* try seek to the position corresponding to the timecode for the sources that failed */ ele = &multSource->sources; while (ele != NULL && ele->source != NULL) { if (!SOURCE_IS_DISABLED(ele)) { if (ele != passedEle && msc_seek(ele->source, position) != 0) { failed = 1; break; } } ele = ele->next; } if (!failed) { /* update sync position */ multSource->syncPosition = position; } return !failed ? 0 : -1; }