/*---------------------------------------------------------------------- | BLT_Decoder_GetVolume +---------------------------------------------------------------------*/ BLT_Result BLT_Decoder_GetVolume(BLT_Decoder* decoder, float* volume) { BLT_MediaNode* output_node; BLT_Result result; /* check parameters */ if (volume == NULL) return BLT_ERROR_INVALID_PARAMETERS; /* default value */ *volume = 0.0f; /* get the volume from the output node */ result = BLT_Stream_GetOutputNode(decoder->stream, &output_node); if (BLT_SUCCEEDED(result) && output_node) { BLT_VolumeControl* volume_control = ATX_CAST(output_node, BLT_VolumeControl); if (volume_control) { result = BLT_VolumeControl_GetVolume(volume_control, volume); } else { result = BLT_ERROR_NOT_SUPPORTED; } ATX_RELEASE_OBJECT(output_node); } else { result = BLT_ERROR_INVALID_STATE; } return result; }
/*---------------------------------------------------------------------- | BLT_Decoder_OutputChanged +---------------------------------------------------------------------*/ static void BLT_Decoder_OutputChanged(BLT_Decoder* decoder, BLT_MediaNode* node) { ATX_RELEASE_OBJECT(decoder->output); if (node) { decoder->output = ATX_CAST(node, BLT_OutputNode); if (decoder->output) { ATX_REFERENCE_OBJECT(decoder->output); } } else { decoder->output = NULL; } }
/*---------------------------------------------------------------------- | BLT_Decoder_Drain +---------------------------------------------------------------------*/ BLT_Result BLT_Decoder_Drain(BLT_Decoder* decoder) { BLT_MediaNode* output_node; BLT_Result result; /* drain the output node */ result = BLT_Stream_GetOutputNode(decoder->stream, &output_node); if (BLT_SUCCEEDED(result) && output_node) { BLT_OutputNode* output_node_interface = ATX_CAST(output_node, BLT_OutputNode); if (output_node_interface) { result = BLT_OutputNode_Drain(output_node_interface); } else { result = BLT_SUCCESS; } ATX_RELEASE_OBJECT(output_node); } else { result = BLT_ERROR_INVALID_STATE; } return result; }
/*---------------------------------------------------------------------- | BLT_Decoder_SetVolume +---------------------------------------------------------------------*/ BLT_Result BLT_Decoder_SetVolume(BLT_Decoder* decoder, float volume) { BLT_MediaNode* output_node; BLT_Result result; /* get the volume from the output node */ result = BLT_Stream_GetOutputNode(decoder->stream, &output_node); if (BLT_SUCCEEDED(result) && output_node) { BLT_VolumeControl* volume_control = ATX_CAST(output_node, BLT_VolumeControl); if (volume_control) { result = BLT_VolumeControl_SetVolume(volume_control, volume); } else { result = BLT_ERROR_NOT_SUPPORTED; } ATX_RELEASE_OBJECT(output_node); } else { result = BLT_ERROR_INVALID_STATE; } return result; }
/*---------------------------------------------------------------------- | Mp4ParserInput_SetStream +---------------------------------------------------------------------*/ BLT_METHOD Mp4ParserInput_SetStream(BLT_InputStreamUser* _self, ATX_InputStream* stream, const BLT_MediaType* stream_media_type) { Mp4Parser* self = ATX_SELF_M(input, Mp4Parser, BLT_InputStreamUser); BLT_Result result = BLT_ERROR_INVALID_MEDIA_FORMAT; /* check media type */ if (stream_media_type == NULL || (stream_media_type->id != self->input.audio_media_type.id && stream_media_type->id != self->input.video_media_type.id)) { return BLT_ERROR_INVALID_MEDIA_TYPE; } /* if we had a file before, release it now */ delete self->input.mp4_file; self->input.mp4_file = NULL; self->input.slow_seek = false; /* create an adapter for the stream */ AP4_ByteStream* stream_adapter = new ATX_InputStream_To_AP4_ByteStream_Adapter(stream); /* check if the source can seek quickly or not */ { ATX_Properties* stream_properties = ATX_CAST(stream, ATX_Properties); if (stream_properties) { ATX_PropertyValue property_value; result = ATX_Properties_GetProperty(stream_properties, ATX_INPUT_STREAM_PROPERTY_SEEK_SPEED, &property_value); if (ATX_SUCCEEDED(result) && property_value.type == ATX_PROPERTY_VALUE_TYPE_INTEGER && property_value.data.integer <= ATX_INPUT_STREAM_SEEK_SPEED_SLOW) { AP4_ByteStream* buffered = new AP4_BufferedInputStream(*stream_adapter); ATX_LOG_FINE("using no-seek mode, source is slow"); stream_adapter->Release(); stream_adapter = buffered; self->input.slow_seek = true; } } } /* parse the MP4 file */ ATX_LOG_FINE("parsing MP4 file"); self->input.mp4_file = new AP4_File(*stream_adapter, AP4_DefaultAtomFactory::Instance, true); /* parse until moov only */ stream_adapter->Release(); // get the global file info AP4_Movie* movie = self->input.mp4_file->GetMovie(); if (movie == NULL) { ATX_LOG_FINE("no movie in file"); goto fail; } // update the stream info BLT_StreamInfo stream_info; stream_info.type = BLT_STREAM_TYPE_MULTIPLEXED; stream_info.id = 0; stream_info.duration = movie->GetDurationMs(); stream_info.mask = BLT_STREAM_INFO_MASK_TYPE | BLT_STREAM_INFO_MASK_ID | BLT_STREAM_INFO_MASK_DURATION; BLT_Stream_SetInfo(ATX_BASE(self, BLT_BaseMediaNode).context, &stream_info); // create a linear reader if the source is slow-seeking if (self->input.slow_seek) { self->input.reader = new AP4_LinearReader(*movie); } // setup the tracks result = Mp4Parser_SetupAudioOutput(self, movie); if (BLT_FAILED(result)) goto fail; result = Mp4Parser_SetupVideoOutput(self, movie); if (BLT_FAILED(result)) goto fail; // check that we have at least one media track if (self->audio_output.track == NULL && self->video_output.track == NULL) { ATX_LOG_FINE("no media track found"); goto fail; } return BLT_SUCCESS; fail: delete self->input.mp4_file; self->input.mp4_file = NULL; self->audio_output.track = NULL; self->video_output.track = NULL; return result; }