예제 #1
0
/*----------------------------------------------------------------------
|    AlsaOutput_Seek
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_Seek(BLT_MediaNode* _self,
                BLT_SeekMode*  mode,
                BLT_SeekPoint* point)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);
    BLT_COMPILER_UNUSED(mode);
    BLT_COMPILER_UNUSED(point);

    /* ignore unless we're prepared */
    if (self->state != BLT_ALSA_OUTPUT_STATE_PREPARED) {
        return BLT_SUCCESS;
    }

    /* reset the device */
    AlsaOutput_Reset(self);

    /* update the media time */
    if (point->mask & BLT_SEEK_POINT_MASK_TIME_STAMP) {
        self->media_time = BLT_TimeStamp_ToNanos(point->time_stamp);
        self->next_media_time = self->media_time;
    } else {
        self->media_time = 0;
        self->next_media_time = 0;
    }
    
    return BLT_SUCCESS;
}
예제 #2
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_Seek
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Seek(BLT_MediaNode* _self,
                         BLT_SeekMode*  mode,
                         BLT_SeekPoint* point)
{
    OsxAudioUnitsOutput* self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult      result;
    
    BLT_COMPILER_UNUSED(mode);
    BLT_COMPILER_UNUSED(point);


    /* flush the queue */
    pthread_mutex_lock(&self->lock);
    ATX_List_Clear(self->packet_queue);
    pthread_mutex_unlock(&self->lock);
    
    /* reset the device */
    result = AudioUnitReset(self->audio_unit, kAudioUnitScope_Input, 0);
    if (result != noErr) {
        ATX_LOG_WARNING_1("AudioUnitReset failed (%d)", (int)result);
    }

    return BLT_SUCCESS;
}
예제 #3
0
/*----------------------------------------------------------------------
|   WaveFormatterModule_Attach
+---------------------------------------------------------------------*/
BLT_METHOD
WaveFormatterModule_Attach(BLT_Module* _self, BLT_Core* core)
{
    WaveFormatterModule* self = ATX_SELF_EX(WaveFormatterModule, BLT_BaseModule, BLT_Module);
    BLT_Registry*        registry;
    BLT_Result           result;

    /* get the registry */
    result = BLT_Core_GetRegistry(core, &registry);
    if (BLT_FAILED(result)) return result;

    /* register the .wav file extensions */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".wav",
                                            "audio/wav");
    if (BLT_FAILED(result)) return result;

    /* register the "audio/wav" type */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        "audio/wav",
        &self->wav_type_id);
    if (BLT_FAILED(result)) return result;
    
    ATX_LOG_FINE_1("WaveFormatterModule::Attach (audio/wav type = %d)", self->wav_type_id);

    return BLT_SUCCESS;
}
예제 #4
0
/*----------------------------------------------------------------------
|    WaveFormatter_Deactivate
+---------------------------------------------------------------------*/
BLT_METHOD
WaveFormatter_Deactivate(BLT_MediaNode* _self)
{
    WaveFormatter* self = ATX_SELF_EX(WaveFormatter, BLT_BaseMediaNode, BLT_MediaNode);

    ATX_LOG_FINER("WaveFormatter::Deactivate");

    /* update the header if needed */
    if (self->output.stream) {
        ATX_Position where = 0;
        ATX_OutputStream_Tell(self->output.stream, &where);
        self->input.size = where;
        if (self->input.size >= BLT_WAVE_FORMATTER_RIFF_HEADER_SIZE) {
            self->input.size -= BLT_WAVE_FORMATTER_RIFF_HEADER_SIZE;
        }

        /* update the header */
        WaveFormatter_UpdateWavHeader(self);

        /* set the stream back to its original position */
        ATX_OutputStream_Seek(self->output.stream, where);
    }

    /* release the output stream */
    ATX_RELEASE_OBJECT(self->output.stream);

    /* call the base class method */
    BLT_BaseMediaNode_Deactivate(_self);

    return BLT_SUCCESS;
}
예제 #5
0
/*----------------------------------------------------------------------
|   WaveParser_Seek
+---------------------------------------------------------------------*/
BLT_METHOD
WaveParser_Seek(BLT_MediaNode* _self,
                BLT_SeekMode*  mode,
                BLT_SeekPoint* point)
{
    WaveParser* self = ATX_SELF_EX(WaveParser, BLT_BaseMediaNode, BLT_MediaNode);

    /* estimate the seek point */
    if (ATX_BASE(self, BLT_BaseMediaNode).context == NULL) return BLT_FAILURE;
    BLT_Stream_EstimateSeekPoint(ATX_BASE(self, BLT_BaseMediaNode).context, *mode, point);
    if (!(point->mask & BLT_SEEK_POINT_MASK_OFFSET)) {
        return BLT_FAILURE;
    }

    /* align the offset to the nearest sample */
    point->offset -= point->offset%(self->output.block_size);

    /* seek to the estimated offset */
    /* seek into the input stream (ignore return value) */
    ATX_InputStream_Seek(self->output.stream, point->offset);
    
    /* set the mode so that the nodes down the chain know the seek has */
    /* already been done on the stream                                  */
    *mode = BLT_SEEK_MODE_IGNORE;

    return BLT_SUCCESS;
}
예제 #6
0
/*----------------------------------------------------------------------
|   DcfParserModule_Attach
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParserModule_Attach(BLT_Module* _self, BLT_Core* core)
{
    DcfParserModule* self = ATX_SELF_EX(DcfParserModule, BLT_BaseModule, BLT_Module);
    BLT_Registry*    registry;
    BLT_Result       result;

    /* get the registry */
    result = BLT_Core_GetRegistry(core, &registry);
    if (BLT_FAILED(result)) return result;

    /* register the ".dcf" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".dcf",
                                            "application/vnd.oma.drm.content");
    if (BLT_FAILED(result)) return result;

    /* register the ".odf" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".odf",
                                            "application/vnd.oma.drm.dcf");
    if (BLT_FAILED(result)) return result;

    /* register the ".oda" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".oda",
                                            "application/vnd.oma.drm.dcf");
    if (BLT_FAILED(result)) return result;

    /* register the ".odv" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".odv",
                                            "application/vnd.oma.drm.dcf");
    if (BLT_FAILED(result)) return result;

    /* get the type id for "application/vnd.oma.drm.content" */
    result = BLT_Registry_GetIdForName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        "application/vnd.oma.drm.content",
        &self->dcf1_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1("DCF Parser Module::Attach (application/vnd.oma.drm.content type = %d)", self->dcf1_type_id);
    
    /* get the type id for "application/vnd.oma.drm.dcf" */
    result = BLT_Registry_GetIdForName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        "application/vnd.oma.drm.dcf",
        &self->dcf2_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1("DCF Parser Module::Attach (application/vnd.oma.drm.dcf type = %d)", self->dcf2_type_id);

    return BLT_SUCCESS;
}
예제 #7
0
/*----------------------------------------------------------------------
|       AlsaOutput_Deactivate
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_Deactivate(BLT_MediaNode* _self)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);

    ATX_LOG_FINER("deactivating output");

    /* close the device */
    AlsaOutput_Close(self);

    return BLT_SUCCESS;
}
예제 #8
0
/*----------------------------------------------------------------------
|       AlsaOutput_Stop
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_Stop(BLT_MediaNode* _self)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);

    ATX_LOG_FINER("stopping output");

    /* reset the device */
    AlsaOutput_Reset(self);

    return BLT_SUCCESS;
}
예제 #9
0
/*----------------------------------------------------------------------
|       AlsaOutput_Activate
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_Activate(BLT_MediaNode* _self, BLT_Stream* stream)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);
    BLT_COMPILER_UNUSED(stream);
        
    ATX_LOG_FINER("activating output");

    /* open the device */
    AlsaOutput_Open(self);

    return BLT_SUCCESS;
}
예제 #10
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_Start
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Start(BLT_MediaNode* _self)
{
    OsxAudioUnitsOutput* self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult      result;
    
    /* start the audio unit */
    result = AudioOutputUnitStart(self->audio_unit);
    if (result != noErr) {
        ATX_LOG_WARNING_1("AudioUnitOutputStart failed (%d)", (int)result);
    }
    
    return BLT_SUCCESS;
}
예제 #11
0
/*----------------------------------------------------------------------
|   AlsaOutput_GetPortByName
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_GetPortByName(BLT_MediaNode*  _self,
                          BLT_CString     name,
                          BLT_MediaPort** port)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);

    if (ATX_StringsEqual(name, "input")) {
        *port = &ATX_BASE(self, BLT_MediaPort);
        return BLT_SUCCESS;
    } else {
        *port = NULL;
        return BLT_ERROR_NO_SUCH_PORT;
    }
}
예제 #12
0
/*----------------------------------------------------------------------
|    DcfParser_Deactivate
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParser_Deactivate(BLT_MediaNode* _self)
{
    DcfParser* self = ATX_SELF_EX(DcfParser, BLT_BaseMediaNode, BLT_MediaNode);

    ATX_LOG_FINER("DcfParser::Deactivate");

    /* release the stream */
    ATX_RELEASE_OBJECT(self->output.stream);

    /* call the base class method */
    BLT_BaseMediaNode_Deactivate(_self);

    return BLT_SUCCESS;
}
예제 #13
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_Resume
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Resume(BLT_MediaNode* _self)
{
    OsxAudioUnitsOutput* self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult      result;

    if (self->paused) {
        ATX_LOG_FINE("resuming output");
        self->paused = BLT_FALSE;
        result = AudioOutputUnitStart(self->audio_unit);
        if (result != noErr) {
            ATX_LOG_WARNING_1("AudioUnitOutputStart failed (%d)", (int)result);
        }
    }
    return BLT_SUCCESS;
}
예제 #14
0
/*----------------------------------------------------------------------
|   DcfParser_GetPortByName
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParser_GetPortByName(BLT_MediaNode*  _self,
                        BLT_CString     name,
                        BLT_MediaPort** port)
{
    DcfParser* self = ATX_SELF_EX(DcfParser, BLT_BaseMediaNode, BLT_MediaNode);

    if (ATX_StringsEqual(name, "input")) {
        *port = &ATX_BASE(&self->input, BLT_MediaPort);
        return BLT_SUCCESS;
    } else if (ATX_StringsEqual(name, "output")) {
        *port = &ATX_BASE(&self->output, BLT_MediaPort);
        return BLT_SUCCESS;
    } else {
        *port = NULL;
        return BLT_ERROR_NO_SUCH_PORT;
    }
}
예제 #15
0
/*----------------------------------------------------------------------
|       OsxAudioUnitsOutput_Deactivate
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Deactivate(BLT_MediaNode* _self)
{
    OsxAudioUnitsOutput* self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult      result;

    ATX_LOG_FINER("OsxAudioUnitsOutput::Deactivate");

    /* un-initialize the device */
    if (self->audio_unit) {
        result = AudioUnitUninitialize(self->audio_unit);
        if (result != noErr) {
            ATX_LOG_WARNING_1("AudioUnitUninitialize failed (%d)", (int)result);
            return BLT_FAILURE;
        }
    }
    
    return BLT_SUCCESS;
}
예제 #16
0
/*----------------------------------------------------------------------
|       AlsaOutput_Resume
+---------------------------------------------------------------------*/
BLT_METHOD
AlsaOutput_Resume(BLT_MediaNode* _self)
{
    AlsaOutput* self = ATX_SELF_EX(AlsaOutput, BLT_BaseMediaNode, BLT_MediaNode);
        
    ATX_LOG_FINER("resuming output");

    /* pause the device */
    switch (self->state) {
      case BLT_ALSA_OUTPUT_STATE_PREPARED:
        snd_pcm_pause(self->device_handle, 0);
        break;

      default:
        /* ignore */
        break;
    }

    return BLT_SUCCESS;
}
예제 #17
0
/*----------------------------------------------------------------------
|    AacDecoder_Seek
+---------------------------------------------------------------------*/
BLT_METHOD
AacDecoder_Seek(BLT_MediaNode* _self,
                BLT_SeekMode*  mode,
                BLT_SeekPoint* point)
{
    AacDecoder* self = ATX_SELF_EX(AacDecoder, BLT_BaseMediaNode, BLT_MediaNode);

    BLT_COMPILER_UNUSED(mode);
    BLT_COMPILER_UNUSED(point);
    
    /* clear the eos flag */
    self->input.eos  = BLT_FALSE;

    /* remove any packets in the output list */
    AacDecoderOutput_Flush(self);

    /* reset the decoder */
    if (self->helix_decoder) AACFlushCodec(self->helix_decoder);

    return BLT_SUCCESS;
}
예제 #18
0
/*----------------------------------------------------------------------
|   AacDecoderModule_Attach
+---------------------------------------------------------------------*/
BLT_METHOD
AacDecoderModule_Attach(BLT_Module* _self, BLT_Core* core)
{
    AacDecoderModule* self = ATX_SELF_EX(AacDecoderModule, BLT_BaseModule, BLT_Module);
    BLT_Registry*           registry;
    BLT_Result              result;

    /* get the registry */
    result = BLT_Core_GetRegistry(core, &registry);
    if (BLT_FAILED(result)) return result;

    /* register the type id */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        BLT_MP4_AUDIO_ES_MIME_TYPE,
        &self->mp4es_type_id);
    if (BLT_FAILED(result)) return result;
    
    ATX_LOG_FINE_1("AacDecoderModule::Attach (" BLT_MP4_AUDIO_ES_MIME_TYPE " = %d)", self->mp4es_type_id);

    return BLT_SUCCESS;
}
예제 #19
0
/*----------------------------------------------------------------------
|    OsxAudioUnitsOutput_Stop
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Stop(BLT_MediaNode* _self)
{
    OsxAudioUnitsOutput* self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult      result;
    

    /* flush the queue */
    pthread_mutex_lock(&self->lock);
    ATX_List_Clear(self->packet_queue);
    pthread_mutex_unlock(&self->lock);

    /* stop the and reset audio unit */
    result = AudioOutputUnitStop(self->audio_unit);
    if (result != noErr) {
        ATX_LOG_WARNING_1("AudioUnitOutputStop failed (%d)", (int)result);
    }
    result = AudioUnitReset(self->audio_unit, kAudioUnitScope_Input, 0);
    if (result != noErr) {
        ATX_LOG_WARNING_1("AudioUnitReset failed (%d)", (int)result);
    }
    
    return BLT_SUCCESS;
}
예제 #20
0
/*----------------------------------------------------------------------
|   AacDecoderModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
AacDecoderModule_Probe(BLT_Module*              _self, 
                       BLT_Core*                core,
                       BLT_ModuleParametersType parameters_type,
                       BLT_AnyConst             parameters,
                       BLT_Cardinal*            match)
{
    AacDecoderModule* self = ATX_SELF_EX(AacDecoderModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);
    
    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* the input and output protocols should be PACKET */
            if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                return BLT_FAILURE;
            }

            /* the input type should be BLT_MP4_ES_MIME_TYPE */
            if (constructor->spec.input.media_type->id != 
                self->mp4es_type_id) {
                return BLT_FAILURE;
            } else {
                /* check the object type id */
                BLT_Mp4AudioMediaType* media_type = (BLT_Mp4AudioMediaType*)constructor->spec.input.media_type;
                if (media_type->base.stream_type != BLT_MP4_STREAM_TYPE_AUDIO) return BLT_FAILURE;
                if (media_type->base.format_or_object_type_id != BLT_AAC_OBJECT_TYPE_ID_MPEG2_AAC_LC &&
                    media_type->base.format_or_object_type_id != BLT_AAC_OBJECT_TYPE_ID_MPEG4_AUDIO) {
                    return BLT_FAILURE;
                }
                if (media_type->base.format_or_object_type_id == BLT_AAC_OBJECT_TYPE_ID_MPEG4_AUDIO) {
                    /* check that this is AAC LC */
                    AacDecoderConfig decoder_config;
                    if (BLT_FAILED(AacDecoderConfig_Parse(media_type->decoder_info, media_type->decoder_info_length, &decoder_config))) {
                        return BLT_FAILURE;
                    }
                    if (decoder_config.object_type != BLT_AAC_OBJECT_TYPE_AAC_LC &&
                        decoder_config.object_type != BLT_AAC_OBJECT_TYPE_SBR) {
                        return BLT_FAILURE;
                    }
                }
            }

            /* the output type should be unspecified, or audio/pcm */
            if (!(constructor->spec.output.media_type->id == 
                  BLT_MEDIA_TYPE_ID_AUDIO_PCM) &&
                !(constructor->spec.output.media_type->id ==
                  BLT_MEDIA_TYPE_ID_UNKNOWN)) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "AacDecoder")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not our name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */
                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("AacDecoderModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
예제 #21
0
/*----------------------------------------------------------------------
|   WaveFormatterModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
WaveFormatterModule_Probe(BLT_Module*              _self, 
                          BLT_Core*                core,
                          BLT_ModuleParametersType parameters_type,
                          BLT_AnyConst             parameters,
                          BLT_Cardinal*            match)
{
    WaveFormatterModule* self = ATX_SELF_EX(WaveFormatterModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* the input protocol should be STREAM_PUSH and the */
            /* output protocol should be STREAM_PUSH            */
            if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PUSH) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PUSH)) {
                return BLT_FAILURE;
            }

            /* the input type should be audio/pcm */
            if (constructor->spec.input.media_type->id !=
                BLT_MEDIA_TYPE_ID_AUDIO_PCM) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "WaveFormatter")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not our name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */

                /* the output type should be audio/wav */
                if (constructor->spec.output.media_type->id !=
                    self->wav_type_id) {
                    return BLT_FAILURE;
                }

                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("WaveFormatterModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
예제 #22
0
/*----------------------------------------------------------------------
|   OsxAudioUnitsOutput_Activate
+---------------------------------------------------------------------*/
BLT_METHOD
OsxAudioUnitsOutput_Activate(BLT_MediaNode* _self, BLT_Stream* stream)
{
    OsxAudioUnitsOutput*   self = ATX_SELF_EX(OsxAudioUnitsOutput, BLT_BaseMediaNode, BLT_MediaNode);
    ComponentResult        result;
    AURenderCallbackStruct callback;
    
    BLT_COMPILER_UNUSED(stream);
        
    ATX_LOG_FINER("start");

    /* select the device */
    if (self->audio_device_id) {
        result = AudioUnitSetProperty(self->audio_unit,
                                      kAudioOutputUnitProperty_CurrentDevice,
                                      kAudioUnitScope_Global,
                                      0,
                                      &self->audio_device_id,
                                      sizeof(self->audio_device_id));
        if (result != noErr) {
            ATX_LOG_WARNING_1("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice) failed (%d)", (int)result);
        }
    }

    /* initialize the output */
    if (self->audio_unit) {
        result = AudioUnitInitialize(self->audio_unit);
        if (result != noErr) {
            ATX_LOG_WARNING_1("AudioUnitInitialize failed (%d)", (int)result);
            return BLT_FAILURE;
        }
    }

    /* set some default audio format */
    {
        AudioStreamBasicDescription audio_desc;
        ATX_SetMemory(&audio_desc, 0, sizeof(audio_desc));
        
        /* setup the audio description */
        audio_desc.mFormatID         = kAudioFormatLinearPCM;
        audio_desc.mFormatFlags      = kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
        audio_desc.mFramesPerPacket  = 1;
        audio_desc.mSampleRate       = 44100;
        audio_desc.mChannelsPerFrame = 2;
        audio_desc.mBitsPerChannel   = 16;
        audio_desc.mBytesPerFrame    = (audio_desc.mBitsPerChannel * audio_desc.mChannelsPerFrame) / 8;
        audio_desc.mBytesPerPacket   = audio_desc.mBytesPerFrame * audio_desc.mFramesPerPacket;
        audio_desc.mReserved         = 0;
        result = AudioUnitSetProperty(self->audio_unit,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Input,
                                      0,
                                      &audio_desc,
                                      sizeof(audio_desc));
        if (result != noErr) {
            ATX_LOG_WARNING_1("AudioUnitSetProperty failed (%d)", (int)result);
            return BLT_FAILURE;
        }
    }

    /* check for downmix based on the number of supported channels */
    OsxAudioUnitsOutput_CheckDownmix(self);
    
    /* setup the callback */
    callback.inputProc = OsxAudioUnitsOutput_RenderCallback;
    callback.inputProcRefCon = _self;
    result = AudioUnitSetProperty(self->audio_unit, 
                                  kAudioUnitProperty_SetRenderCallback, 
                                  kAudioUnitScope_Input, 
                                  0,
                                  &callback, 
                                  sizeof(callback));
    if (result != noErr) {
        ATX_LOG_SEVERE_1("AudioUnitSetProperty failed when setting callback (%d)", (int)result);
        return BLT_FAILURE;
    }

    return BLT_SUCCESS;
}
예제 #23
0
/*----------------------------------------------------------------------
|   Mp4ParserModule_Attach
+---------------------------------------------------------------------*/
BLT_METHOD
Mp4ParserModule_Attach(BLT_Module* _self, BLT_Core* core)
{
    Mp4ParserModule* self = ATX_SELF_EX(Mp4ParserModule, BLT_BaseModule, BLT_Module);
    BLT_Registry*    registry;
    BLT_Result       result;

    /* get the registry */
    result = BLT_Core_GetRegistry(core, &registry);
    if (BLT_FAILED(result)) return result;

    /* register the ".mp4" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".mp4",
                                            "video/mp4");
    if (BLT_FAILED(result)) return result;

    /* register the ".m4a" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".m4a",
                                            "audio/mp4");
    if (BLT_FAILED(result)) return result;

    /* register the ".m4v" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".m4v",
                                            "video/mp4");
    if (BLT_FAILED(result)) return result;

    /* register the ".m4p" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".m4p",
                                            "video/mp4");
    if (BLT_FAILED(result)) return result;

    /* register the ".3gp" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".3gp",
                                            "video/mp4");
    if (BLT_FAILED(result)) return result;

    /* register the ".3gp" file extension */
    result = BLT_Registry_RegisterExtension(registry, 
                                            ".mov",
                                            "video/mp4");
    if (BLT_FAILED(result)) return result;

    /* get the type id for "audio/mp4" */
    result = BLT_Registry_GetIdForName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        "audio/mp4",
        &self->mp4_audio_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1("audio/mp4 type = %d", self->mp4_audio_type_id);
    
    /* get the type id for "video/mp4" */
    result = BLT_Registry_GetIdForName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        "video/mp4",
        &self->mp4_video_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1("video/mp4 type = %d", self->mp4_video_type_id);

    /* register the type id for BLT_MP4_AUDIO_ES_MIME_TYPE */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        BLT_MP4_AUDIO_ES_MIME_TYPE,
        &self->mp4_audio_es_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1(BLT_MP4_AUDIO_ES_MIME_TYPE " type = %d", self->mp4_audio_es_type_id);

    /* register the type id for BLT_MP4_VIDEO_ES_MIME_TYPE */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        BLT_MP4_VIDEO_ES_MIME_TYPE,
        &self->mp4_video_es_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1(BLT_MP4_VIDEO_ES_MIME_TYPE " type = %d", self->mp4_video_es_type_id);

    /* register the type id for BLT_ISO_BASE_AUDIO_ES_MIME_TYPE */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        BLT_ISO_BASE_AUDIO_ES_MIME_TYPE,
        &self->iso_base_audio_es_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1(BLT_ISO_BASE_AUDIO_ES_MIME_TYPE " type = %d", self->iso_base_audio_es_type_id);

    /* register the type id for BLT_ISO_BASE_VIDEO_ES_MIME_TYPE */
    result = BLT_Registry_RegisterName(
        registry,
        BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
        BLT_ISO_BASE_VIDEO_ES_MIME_TYPE,
        &self->iso_base_video_es_type_id);
    if (BLT_FAILED(result)) return result;
    ATX_LOG_FINE_1(BLT_ISO_BASE_VIDEO_ES_MIME_TYPE " type = %d", self->iso_base_video_es_type_id);

    /* register mime type aliases */
    BLT_Registry_RegisterNameForId(registry, 
                                   BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
                                   "audio/m4a", self->mp4_audio_type_id);
    BLT_Registry_RegisterNameForId(registry, 
                                   BLT_REGISTRY_NAME_CATEGORY_MEDIA_TYPE_IDS,
                                   "video/m4v", self->mp4_video_type_id);

    return BLT_SUCCESS;
}
예제 #24
0
/*----------------------------------------------------------------------
|   Mp4Parser_Seek
+---------------------------------------------------------------------*/
BLT_METHOD
Mp4Parser_Seek(BLT_MediaNode* _self,
               BLT_SeekMode*  mode,
               BLT_SeekPoint* point)
{
    Mp4Parser* self = ATX_SELF_EX(Mp4Parser, BLT_BaseMediaNode, BLT_MediaNode);

    /* estimate the seek point */
    if (ATX_BASE(self, BLT_BaseMediaNode).context == NULL) return BLT_FAILURE;
    BLT_Stream_EstimateSeekPoint(ATX_BASE(self, BLT_BaseMediaNode).context, *mode, point);
    if (!(point->mask & BLT_SEEK_POINT_MASK_TIME_STAMP)) {
        return BLT_FAILURE;
    }

    /* seek to the estimated offset on all tracks */
    AP4_Ordinal sample_index = 0;
    AP4_UI32    ts_ms = point->time_stamp.seconds*1000+point->time_stamp.nanoseconds/1000000;
    if (self->video_output.track) {
        AP4_Result result = self->video_output.track->GetSampleIndexForTimeStampMs(ts_ms, sample_index);
        if (AP4_FAILED(result)) {
            ATX_LOG_WARNING_1("video GetSampleIndexForTimeStampMs failed (%d)", result);
            return BLT_FAILURE;
        }
        ATX_LOG_FINE_1("seeking to video time %d ms", ts_ms);
        
        // go to the nearest sync sample
        self->video_output.sample = self->video_output.track->GetNearestSyncSampleIndex(sample_index);
        if (self->input.reader) {
            self->input.reader->SetSampleIndex(self->video_output.track->GetId(), self->video_output.sample);
        }
        ATX_LOG_FINE_1("seeking to video sync sample %d", self->video_output.sample);
        
        // compute the timestamp of the video sample we're seeking to, so we can pick an audio
        // sample that is close in time (there are many more audio sync points than video)
        AP4_Sample sample;
        if (AP4_SUCCEEDED(self->video_output.track->GetSample(self->video_output.sample, sample))) {
            AP4_UI32 media_timescale = self->video_output.track->GetMediaTimeScale();
            if (media_timescale) {
                ts_ms = (AP4_UI32)((((AP4_UI64)sample.GetCts())*1000)/media_timescale);
                ATX_LOG_FINE_1("sync sample time is %d ms", ts_ms);
            }
        } else {
            ATX_LOG_FINE_1("unable to get sample info for sample %d", self->video_output.sample);
        }
    }
    if (self->audio_output.track) {
        AP4_Result result = self->audio_output.track->GetSampleIndexForTimeStampMs(ts_ms, sample_index);
        if (AP4_FAILED(result)) {
            ATX_LOG_WARNING_1("audio GetSampleIndexForTimeStampMs failed (%d)", result);
            return BLT_FAILURE;
        }
        self->audio_output.sample = sample_index;
        if (self->input.reader) {
            self->input.reader->SetSampleIndex(self->audio_output.track->GetId(), sample_index);
        }
    }
    
    /* set the mode so that the nodes down the chain know the seek has */
    /* already been done on the stream                                 */
    *mode = BLT_SEEK_MODE_IGNORE;

    return BLT_SUCCESS;
}
예제 #25
0
/*----------------------------------------------------------------------
|   DcfParserModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
DcfParserModule_Probe(BLT_Module*              _self, 
                      BLT_Core*                core,
                      BLT_ModuleParametersType parameters_type,
                      BLT_AnyConst             parameters,
                      BLT_Cardinal*            match)
{
    DcfParserModule* self = ATX_SELF_EX(DcfParserModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = 
                (BLT_MediaNodeConstructor*)parameters;

            /* we need the input protocol to be STREAM_PULL and the output */
            /* protocol to be STREAM_PULL                                  */
             if ((constructor->spec.input.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.input.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL) ||
                (constructor->spec.output.protocol !=
                 BLT_MEDIA_PORT_PROTOCOL_ANY &&
                 constructor->spec.output.protocol != 
                 BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL)) {
                return BLT_FAILURE;
            }

            /* we need the input media type to be 'application/vnd.oma.drm.content' */
            /* or 'application/vnd.oma.drm.dcf'                                     */
            if (constructor->spec.input.media_type->id != self->dcf1_type_id &&
                constructor->spec.input.media_type->id != self->dcf2_type_id) {
                return BLT_FAILURE;
            }

            /* the output type should be unknown at this point */
            if (constructor->spec.output.media_type->id != 
                BLT_MEDIA_TYPE_ID_UNKNOWN) {
                return BLT_FAILURE;
            }

            /* compute the match level */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "DcfParser")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                } else {
                    /* not out name */
                    return BLT_FAILURE;
                }
            } else {
                /* we're probed by protocol/type specs only */
                *match = BLT_MODULE_PROBE_MATCH_MAX - 10;
            }

            ATX_LOG_FINE_1("DcfParserModule::Probe - Ok [%d]", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}
예제 #26
0
/*----------------------------------------------------------------------
|   Mp4ParserModule_Probe
+---------------------------------------------------------------------*/
BLT_METHOD
Mp4ParserModule_Probe(BLT_Module*              _self, 
                      BLT_Core*                core,
                      BLT_ModuleParametersType parameters_type,
                      BLT_AnyConst             parameters,
                      BLT_Cardinal*            match)
{
    Mp4ParserModule* self = ATX_SELF_EX(Mp4ParserModule, BLT_BaseModule, BLT_Module);
    BLT_COMPILER_UNUSED(core);

    switch (parameters_type) {
      case BLT_MODULE_PARAMETERS_TYPE_MEDIA_NODE_CONSTRUCTOR:
        {
            BLT_MediaNodeConstructor* constructor = (BLT_MediaNodeConstructor*)parameters;

            /* check if we're being probed by name */
            if (constructor->name != NULL) {
                /* we're being probed by name */
                if (ATX_StringsEqual(constructor->name, "com.bluetune.parsers.mp4")) {
                    /* our name */
                    *match = BLT_MODULE_PROBE_MATCH_EXACT;
                    return BLT_SUCCESS;
                } else {
                    /* not out name */
                    *match = 0;
                    return BLT_FAILURE;
                }
            }
            
            /* we need the input protocol to be STREAM_PULL and the output */
            /* protocol to be PACKET                                       */
             if ((constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                  constructor->spec.input.protocol  != BLT_MEDIA_PORT_PROTOCOL_STREAM_PULL) ||
                 (constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_ANY &&
                  constructor->spec.output.protocol != BLT_MEDIA_PORT_PROTOCOL_PACKET)) {
                return BLT_FAILURE;
            }

            /* we need the input media type to be 'audio/mp4' or 'video/mp4' */
            if (constructor->spec.input.media_type->id != self->mp4_audio_type_id &&
                constructor->spec.input.media_type->id != self->mp4_video_type_id) {
                return BLT_FAILURE;
            }

            /* the output type should be unknown at this point */
            if (constructor->spec.output.media_type->id != BLT_MEDIA_TYPE_ID_UNKNOWN) {
                return BLT_FAILURE;
            }

            /* set the match level */
            *match = BLT_MODULE_PROBE_MATCH_MAX - 10;

            ATX_LOG_FINE_1("match %d", *match);
            return BLT_SUCCESS;
        }    
        break;

      default:
        break;
    }

    return BLT_FAILURE;
}