示例#1
0
nsresult
WMFReader::SeekInternal(int64_t aTargetUs)
{
  DECODER_LOG("WMFReader::Seek() %lld", aTargetUs);

  MOZ_ASSERT(OnTaskQueue());
#ifdef DEBUG
  bool canSeek = false;
  GetSourceReaderCanSeek(mSourceReader, canSeek);
  NS_ASSERTION(canSeek, "WMFReader::Seek() should only be called if we can seek!");
#endif

  nsresult rv = ResetDecode();
  NS_ENSURE_SUCCESS(rv, rv);

  // Mark that we must recapture the audio frame count from the next sample.
  // WMF doesn't set a discontinuity marker when we seek to time 0, so we
  // must remember to recapture the audio frame offset and reset the frame
  // sum on the next audio packet we decode.
  mMustRecaptureAudioPosition = true;

  AutoPropVar var;
  HRESULT hr = InitPropVariantFromInt64(UsecsToHNs(aTargetUs), &var);
  NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);

  hr = mSourceReader->SetCurrentPosition(GUID_NULL, var);
  NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);

  return NS_OK;
}
示例#2
0
/*
EW: This is part of the fix for seeking because calling SetCurrentPosition was failing.
It is now split up to set a flag that seeking needs to be done,
and we call this at a time that seems to work (in the read).
*/ 
static void Internal_DoSeek(Sound_Sample* sample)
{
	Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque;
	MediaFoundationFileContainer* media_foundation_file_container = (MediaFoundationFileContainer*)internal->decoder_private;
	__int64 mf_seek_target = media_foundation_file_container->seekTargetPosition;
	PROPVARIANT prop_variant;
	HRESULT hr = S_OK;

	// this doesn't fail, see MS's implementation
	hr = InitPropVariantFromInt64(mf_seek_target, &prop_variant);

	// http://msdn.microsoft.com/en-us/library/dd374668(v=VS.85).aspx
	hr = media_foundation_file_container->sourceReader->SetCurrentPosition(GUID_NULL, prop_variant);
	if(FAILED(hr))
	{
		// nothing we can do here as we can't fail (no facility to other than
		// crashing mixxx)
	//		sample->flags |= SOUND_SAMPLEFLAG_ERROR;
		// more C++ BS
		sample->flags = (SoundDecoder_SampleFlags)(sample->flags | SOUND_SAMPLEFLAG_ERROR);
		if (hr == MF_E_INVALIDREQUEST)
		{
			SNDERR("WindowsMediaFoundation failed to seek: Sample requests still pending\n");
		}
		else
		{
			SNDERR("WindowsMediaFoundation failed to seek\n");
		}
	}

	PropVariantClear(&prop_variant);
}
示例#3
0
nsresult
WMFReader::Seek(int64_t aTargetUs,
                int64_t aStartTime,
                int64_t aEndTime,
                int64_t aCurrentTime)
{
  LOG("WMFReader::Seek() %lld", aTargetUs);

  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
  if (!mCanSeek) {
    return NS_ERROR_FAILURE;
  }

  nsresult rv = ResetDecode();
  NS_ENSURE_SUCCESS(rv, rv);

  AutoPropVar var;
  HRESULT hr = InitPropVariantFromInt64(UsecsToHNs(aTargetUs), &var);
  NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);

  hr = mSourceReader->SetCurrentPosition(GUID_NULL, var);
  NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);

  return DecodeToTarget(aTargetUs);
}
/*virtual */bool MFMovieSource::Jump(long long frameNo)
{
  PROPVARIANT prop;
  InitPropVariantFromInt64(frameNo, &prop);
  this->_reader->SetCurrentPosition(GUID_NULL, prop);
  PropVariantClear(&prop);

  long long time = 0;
  auto img = this->Read((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &time);

  return !!img;
}/*
SINT SoundSourceMediaFoundation::seekSampleFrame(
        SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(frameIndex));
    if (sDebug) {
        qDebug() << "seekSampleFrame()" << frameIndex;
    }
    qint64 mfSeekTarget(mfFromFrame(frameIndex, getSamplingRate()) - 1);
    // minus 1 here seems to make our seeking work properly, otherwise we will
    // (more often than not, maybe always) seek a bit too far (although not
    // enough for our calculatedFrameFromMF <= nextFrame assertion in ::read).
    // Has something to do with 100ns MF units being much smaller than most
    // frame offsets (in seconds) -bkgood
    SINT result = m_iCurrentPosition;
    if (m_dead) {
        return result;
    }

    PROPVARIANT prop;
    HRESULT hr;

    // this doesn't fail, see MS's implementation
    hr = InitPropVariantFromInt64(mfSeekTarget < 0 ? 0 : mfSeekTarget, &prop);

    hr = m_pReader->Flush(MF_SOURCE_READER_FIRST_AUDIO_STREAM);
    if (FAILED(hr)) {
        qWarning() << "SSMF: failed to flush before seek";
    }

    // http://msdn.microsoft.com/en-us/library/dd374668(v=VS.85).aspx
    hr = m_pReader->SetCurrentPosition(GUID_NULL, prop);
    if (FAILED(hr)) {
        // nothing we can do here as we can't fail (no facility to other than
        // crashing mixxx)
        qWarning() << "SSMF: failed to seek"
                << (hr == MF_E_INVALIDREQUEST ?
                        "Sample requests still pending" : "");
    } else {
        result = frameIndex;
    }
    PropVariantClear(&prop);

    // record the next frame so that we can make sure we're there the next
    // time we get a buffer from MFSourceReader
    m_nextFrame = frameIndex;
    m_seeking = true;
    m_iCurrentPosition = result;
    return result;
}
SINT SoundSourceMediaFoundation::seekSampleFrame(
        SINT frameIndex) {
    DEBUG_ASSERT(isValidFrameIndex(m_currentFrameIndex));

    if (frameIndex >= getMaxFrameIndex()) {
        // EOF
        m_currentFrameIndex = getMaxFrameIndex();
        return m_currentFrameIndex;
    }

    if (frameIndex > m_currentFrameIndex) {
        // seeking forward
        SINT skipFramesCount = frameIndex - m_currentFrameIndex;
        // When to prefer skipping over seeking:
        // 1) The sample buffer would be discarded before seeking anyway and
        //    skipping those already decoded samples effectively costs nothing
        // 2) After seeking we need to decode at least kNumberOfPrefetchFrames
        //    before reaching the actual target position -> Only seek if we
        //    need to decode more than  2 * kNumberOfPrefetchFrames frames
        //    while skipping
        SINT skipFramesCountMax =
                samples2frames(m_sampleBuffer.getSize()) +
                2 * kNumberOfPrefetchFrames;
        if (skipFramesCount <= skipFramesCountMax) {
            skipSampleFrames(skipFramesCount);
        }
    }
    if (frameIndex == m_currentFrameIndex) {
        return m_currentFrameIndex;
    }

    // Discard decoded samples
    m_sampleBuffer.reset();

    // Invalidate current position (end of stream)
    m_currentFrameIndex = getMaxFrameIndex();

    if (m_pSourceReader == nullptr) {
        // reader is dead
        return m_currentFrameIndex;
    }

    // Jump to a position before the actual seeking position.
    // Prefetching a certain number of frames is necessary for
    // sample accurate decoding. The decoder needs to decode
    // some frames in advance to produce the same result at
    // each position in the stream.
    SINT seekIndex = std::max(SINT(frameIndex - kNumberOfPrefetchFrames), AudioSource::getMinFrameIndex());

    LONGLONG seekPos = m_streamUnitConverter.fromFrameIndex(seekIndex);
    DEBUG_ASSERT(seekPos >= 0);
    PROPVARIANT prop;
    HRESULT hrInitPropVariantFromInt64 =
            InitPropVariantFromInt64(seekPos, &prop);
    DEBUG_ASSERT(SUCCEEDED(hrInitPropVariantFromInt64)); // never fails
    HRESULT hrSetCurrentPosition =
            m_pSourceReader->SetCurrentPosition(GUID_NULL, prop);
    PropVariantClear(&prop);
    if (SUCCEEDED(hrSetCurrentPosition)) {
        // NOTE(uklotzde): After SetCurrentPosition() the actual position
        // of the stream is unknown until reading the next samples from
        // the reader. Please note that the first sample decoded after
        // SetCurrentPosition() may start BEFORE the actual target position.
        // See also: https://msdn.microsoft.com/en-us/library/windows/desktop/dd374668(v=vs.85).aspx
        //   "The SetCurrentPosition method does not guarantee exact seeking." ...
        //   "After seeking, the application should call IMFSourceReader::ReadSample
        //    and advance to the desired position.
        SINT skipFramesCount = frameIndex - seekIndex;
        if (skipFramesCount > 0) {
            // We need to fetch at least 1 sample from the reader to obtain the
            // current position!
            skipSampleFrames(skipFramesCount);
            // Now m_currentFrameIndex reflects the actual position of the reader
            if (m_currentFrameIndex < frameIndex) {
                // Skip more samples if frameIndex has not yet been reached
                skipSampleFrames(frameIndex - m_currentFrameIndex);
            }
            if (m_currentFrameIndex != frameIndex) {
                qWarning() << kLogPreamble
                        << "Seek to frame"
                        << frameIndex
                        << "failed";
                // Jump to end of stream (= invalidate current position)
                m_currentFrameIndex = getMaxFrameIndex();
            }
        } else {
            // We are at the beginning of the stream and don't need
            // to skip any frames. Calling IMFSourceReader::ReadSample
            // is not necessary in this special case.
            DEBUG_ASSERT(frameIndex == AudioSource::getMinFrameIndex());
            m_currentFrameIndex = frameIndex;
        }
    } else {
        qWarning() << kLogPreamble
                << "IMFSourceReader::SetCurrentPosition() failed"
                << hrSetCurrentPosition;
        safeRelease(&m_pSourceReader); // kill the reader
    }

    return m_currentFrameIndex;
}
示例#7
0
// This routine initializes the sensor to its default properties
NTSTATUS
PedometerDevice::Initialize(
    _In_ WDFDEVICE Device, // WDFDEVICE object
    _In_ SENSOROBJECT SensorInstance // SENSOROBJECT for each sensor instance
    )
{
    ULONG Size = 0;
    WDF_OBJECT_ATTRIBUTES MemoryAttributes;
    WDFMEMORY MemoryHandle = NULL;
    FILETIME Time = {};
    WDF_OBJECT_ATTRIBUTES TimerAttributes;
    WDF_TIMER_CONFIG TimerConfig;
    NTSTATUS Status = STATUS_SUCCESS;
    PHardwareSimulator pSimulator = nullptr;
    ULONG HistorySizeInRecords = 0;

    SENSOR_FunctionEnter();

    // Store device and instance
    m_FxDevice = Device;
    m_SensorInstance = SensorInstance;
    m_Started = FALSE;
    m_HistoryRetrievalStarted = FALSE;

    // Initialize the pedometer simulator
    Status = HardwareSimulator::Initialize(Device, &m_SimulatorInstance);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", Status);
        goto Exit;
    }

    pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        goto Exit;
    }

    // Create Lock
    Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Create timer object for polling sensor samples
    WDF_TIMER_CONFIG_INIT(&TimerConfig, PedometerDevice::OnTimerExpire);
    WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
    TimerAttributes.ParentObject = SensorInstance;
    TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfTimerCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Supported Data-Fields
    Size = SENSOR_PROPERTY_LIST_SIZE(PEDOMETER_DATAFIELD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pSupportedDataFields));
    if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size);
    m_pSupportedDataFields->Count = PEDOMETER_DATAFIELD_COUNT;

    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_TIMESTAMP] = PKEY_SensorData_Timestamp;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_FIRST_AFTER_RESET] = PKEY_SensorData_PedometerReset;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_TYPE] = PKEY_SensorData_PedometerStepType;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_COUNT] = PKEY_SensorData_PedometerStepCount;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_DURATION] = PKEY_SensorData_PedometerStepDuration_Ms;

    // Data
    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_DATA_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pData));
    if (!NT_SUCCESS(Status) || nullptr == m_pData)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pData, Size);
    m_pData->Count = PEDOMETER_DATA_COUNT;

    m_pData->List[PEDOMETER_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
    GetSystemTimePreciseAsFileTime(&Time);
    InitPropVariantFromFileTime(&Time, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));

    m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Key = PKEY_SensorData_PedometerReset;
    InitPropVariantFromBoolean(FALSE, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Unknown), &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(600, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(123, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Walking), &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(700, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(456, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Running), &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(800, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(789, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));

    m_LastSample.Timestamp = Time;
    m_LastSample.UnknownStepCount = 0;
    m_LastSample.UnknownStepDurationMs = 0;
    m_LastSample.WalkingStepCount = 0;
    m_LastSample.WalkingStepDurationMs = 0;
    m_LastSample.RunningStepCount = 0;
    m_LastSample.RunningStepDurationMs = 0;
    m_LastSample.IsFirstAfterReset = FALSE;

    // Get the History Size to populate 'PKEY_SensorHistory_MaxSize_Bytes'
    // Typically the size needed to store a history record on the hardware is 
    // smaller than the size needed to represent a history record as a 
    // SENSOR_COLLECTION_LIST (collection of SENSOR_VALUE_PAIRs)
    // To be able to accurately represent the size of the history on the 
    // hardware (simulator in this case), get the number of records that the HW  
    // can store and multiply it with the marshalled size of 
    // SENSOR_COLLECTION_LIST needed to represent a single record.

    HistorySizeInRecords = pSimulator->GetHistorySizeInRecords();
    m_HistorySupported = (HistorySizeInRecords > 0) ? TRUE : FALSE;

    // Pedometer History format is exactly same as it's data sample.
    // so, we can simply reuse the 'm_pData' to compute the marshalled size
    // History Retrieval is not WOW64 compatible and hence will not involve 
    // serializing the collections list. Should Use 
    // CollectionsListGetMarshalledSizeWithoutSerialization  instead of 
    // CollectionsListGetMarshalledSize when dealing with History Collection list.
    m_HistoryMarshalledRecordSize = CollectionsListGetMarshalledSizeWithoutSerialization(m_pData);

    // Sensor Enumeration Properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ENUMERATION_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
        PagedPool,
        SENSOR_POOL_TAG_PEDOMETER,
        Size,
        &MemoryHandle,
        reinterpret_cast<PVOID*>(&m_pEnumerationProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size);
    m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT;

    m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer,
        &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value));

    m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
    InitPropVariantFromString(L"Microsoft",
        &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value));

    m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model;
    InitPropVariantFromString(L"PEDOMETER",
        &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));

    m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
    InitPropVariantFromCLSID(GUID_PedometerDevice_UniqueID,
        &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value));

    m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category;
    InitPropVariantFromCLSID(GUID_SensorCategory_Motion,
        &(m_pEnumerationProperties->List[SENSOR_CATEGORY].Value));

    m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary;
    InitPropVariantFromBoolean(FALSE,
        &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); // This value should be set to TRUE if multiple pedometers
                                                                    // exist on the system and this sensor is the primary sensor

    m_pEnumerationProperties->List[SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
        &(m_pEnumerationProperties->List[SENSOR_POWER].Value));

    m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
        (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
        0),
        &(m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Value));

    m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Value));

    // Sensor Properties
    m_Interval = Pedometer_Default_MinDataInterval_Ms;

    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size);
    m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT;

    m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State;
    InitPropVariantFromUInt32(SensorState_Initializing, 
                              &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

    m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
    InitPropVariantFromUInt32(Pedometer_Default_MinDataInterval_Ms, 
                              &(m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
    InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pData), 
                              &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer, 
                                 &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
                                &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
                                (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
                                0),
                                &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Key = PKEY_SensorHistory_Interval_Ms;
    InitPropVariantFromUInt32(pSimulator->GetHistoryIntervalInMs(),
                                &(m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Key = PKEY_SensorHistory_MaximumRecordSize_Bytes;
    InitPropVariantFromUInt32(m_HistoryMarshalledRecordSize,
        &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Value));

    // Data field properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT);
    
    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pDataFieldProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pDataFieldProperties, Size);
    m_pDataFieldProperties->Count = SENSOR_DATA_FIELD_PROPERTY_COUNT;

    m_pDataFieldProperties->List[SENSOR_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
    InitPropVariantFromInt64(PedometerDevice_StepCount_Resolution,
                             &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value));

    m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Minimum,
                             &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value));

    m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Maximum,
                             &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value));

    // Set default threshold
    m_FirstSample = TRUE;

    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_THRESHOLD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
                             PagedPool,
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pThresholds));
    if (!NT_SUCCESS(Status) || nullptr == m_pThresholds)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size);
    m_pThresholds->Count = PEDOMETER_THRESHOLD_COUNT;

    m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(Pedometer_Default_Threshold_StepCount,
                             &(m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Value));

    m_CachedThreshold = Pedometer_Default_Threshold_StepCount;
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
示例#8
0
// This routine is called by worker thread to read a single sample, compare threshold
// and push it back to CLX. It simulates hardware thresholding by only generating data
// when the change of data is greater than threshold.
NTSTATUS
PedometerDevice::GetData(
)
{
    PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
    BOOLEAN DataReady = FALSE;
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG CachedStepCountLimit = 0;
    ULONG LastStepCountLimit = 0;
    PedometerSample Sample = {};

    SENSOR_FunctionEnter();

    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        goto Exit;
    }

    Status = pSimulator->GetSample(&Sample);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! GetSample failed %!STATUS!", Status);
        goto Exit;
    }

    if (FALSE != m_FirstSample)
    {
        Status = GetPerformanceTime(&m_StartTime);
        if (!NT_SUCCESS(Status))
        {
            m_StartTime = 0;
            TraceError("PED %!FUNC! GetPerformanceTime failed %!STATUS!", Status);
        }

        m_SampleCount = 0;

        DataReady = TRUE;
    }
    else
    {
        if (0 == m_CachedThreshold || FALSE != Sample.IsFirstAfterReset)
        {
            // Streaming mode
            DataReady = TRUE;
        }
        else
        {
            if (FAILED(ULongAdd(Sample.UnknownStepCount, Sample.WalkingStepCount, &CachedStepCountLimit)) ||
                FAILED(ULongAdd(Sample.RunningStepCount, CachedStepCountLimit, &CachedStepCountLimit)))
            {
                // If an overflow happened, we assume we reached the threshold
                // in other words, there is no threshold value that can be larger
                // than an overflowed value.
                DataReady = TRUE;
            }
            else if (FAILED(ULongAdd(m_LastSample.UnknownStepCount, m_LastSample.WalkingStepCount, &LastStepCountLimit)) ||
                     FAILED(ULongAdd(m_LastSample.RunningStepCount, LastStepCountLimit, &LastStepCountLimit)))
            {
                // If an overflow happened, we assume we reached the threshold
                // in other words, there is no threshold value that can be larger
                // than an overflowed value.
                DataReady = TRUE;
            }
            else if ((LastStepCountLimit < m_CachedThreshold && CachedStepCountLimit >= m_CachedThreshold) ||
                     (FALSE != Sample.IsFirstAfterReset))
            {
                // Compare the change of data to threshold, and only push the data back to 
                // clx if the change exceeds threshold or if this is the first sample after reset. This is usually done in HW.
                DataReady = TRUE;
            }
        }
    }

    if (FALSE != DataReady)
    {
        // update last sample
        m_LastSample = Sample;

        // push to clx
        InitPropVariantFromBoolean(m_LastSample.IsFirstAfterReset, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));
        InitPropVariantFromUInt32(PedometerStepType_Unknown, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.UnknownStepDurationMs, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.UnknownStepCount, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));
        InitPropVariantFromUInt32(PedometerStepType_Walking, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.WalkingStepDurationMs, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.WalkingStepCount, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));
        InitPropVariantFromUInt32(PedometerStepType_Running, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.RunningStepDurationMs, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.RunningStepCount, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));

        // reset IsFirstAfterReset
        m_LastSample.IsFirstAfterReset = FALSE;

        InitPropVariantFromFileTime(&m_LastSample.Timestamp, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));

        SensorsCxSensorDataReady(m_SensorInstance, m_pData);
        m_FirstSample = FALSE;
    }
    else
    {
        Status = STATUS_DATA_NOT_ACCEPTED;
        TraceInformation("PED %!FUNC! Data did NOT meet the threshold");
    }

    SENSOR_FunctionExit(Status);

Exit:
    return Status;
}