| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| library fuchsia.mediacodec; |
| |
| using fuchsia.media; |
| |
| // CreateDecoder_Params |
| // |
| // Input parameters for creating a decoder (audio or video). |
| // |
| |
| /// Whether buffers need to be secure. If not specified, the default is OFF. |
| /// |
| /// This enum may have additional values added later; code handling this type |
| /// should be written with this in mind. For example, in C++, having a |
| /// "default" case in any switch statement on this type will avoid compilation |
| /// warnings/errors when a new value is added. |
| // |
| // Later we can add DYNAMIC, as needed. |
| enum SecureMemoryMode : uint32 { |
| // Normal memory. This is the default if a field of this type is not set. |
| OFF = 0; |
| // Secure memory. |
| ON = 1; |
| }; |
| |
| table CreateDecoder_Params { |
| /// Input mime type for a decoder. |
| /// |
| /// The recognized mime types for now: |
| /// video/h264 |
| /// video/vp9 |
| /// audio/aac |
| /// input_details.oob_bytes must be an AudioSpecificConfig() as defined |
| /// by AAC spec. |
| /// audio/sbc |
| /// input_details.oob_bytes must be Codec Specific Information Elements |
| /// for SBC as defined by the A2DP spec. |
| 1: fuchsia.media.FormatDetails input_details; |
| |
| // The settings below nail down more details. |
| |
| /// This must be true in order for the client to be permitted to put a |
| /// timestamp on an input packet, which is in turn required to get any |
| /// timestamps on any output packets. |
| /// |
| /// It is always legal to provide separate Access Units (henceforth AUs) to a |
| /// decoder, but this boolean must be true for a decoder to accept and |
| /// propagate timestamp values. |
| /// |
| /// This must be true when creating a video encoder, or the CodecFactory |
| /// channel will close. |
| // TODO(FIDL-609): Default to false. |
| 2: bool promise_separate_access_units_on_input; |
| |
| // "require" fields: |
| // |
| // Specifying any of these "require" fields can result in failure to get a |
| // Codec if there's no suitable codec. None of these correspond to any |
| // required features of a codec server. |
| // |
| // TODO(dustingreen): implement filtering codecs based on these fields. |
| |
| /// Require that the selected codec be capable of accepting input where |
| /// AUs are not separated into separate packets. |
| /// |
| /// This does not imply that the decoder can find the start of the first AU; |
| /// for that see require_can_find_start. This does not imply that the decoder |
| /// can re-sync on its own if the stream data is damaged; for that see |
| /// require_can_re_sync. |
| /// |
| /// If both promise_separate_access_units_on_input and |
| /// require_can_stream_bytes_input are true, the CodecFactory channel will |
| /// close. |
| /// |
| /// If this is false, the client must feed separate AUs on the fuchsia.ui.input. This |
| /// must be false for a video encoder, and if true the CodecFactory channel |
| /// will close. |
| /// |
| /// Unless a client demands a decoder capable of taking concatenated AUs |
| /// (require_can_stream_bytes_input true), the client must feed a decoder |
| /// separate AUs. This means the client cannot have parts of two separate AUs |
| /// in the same packet, unless require_can_stream_bytes_input is true. |
| // TODO(FIDL-609): Default to false. |
| 3: bool require_can_stream_bytes_input; |
| |
| /// A decoder is allowed to be capable of streaming bytes but not capable of |
| /// searching for the start of the first usable AU. To require both, set both |
| /// require_can_stream_bytes_input and require_can_find_start. Setting |
| /// require_can_find_start without require_can_stream_bytes_input is invalid. |
| /// |
| /// With require_can_stream_bytes_input true but require_can_find_start false, |
| /// the client must start the first packet with the start of an AU, but can |
| /// send a stream of bytes after that. |
| // TODO(FIDL-609): Default to false. |
| 4: bool require_can_find_start; |
| |
| /// On problematic input data, all decoders are expected to at least be able to |
| /// close the channel rather than getting stuck in a failed and/or broken |
| /// state. |
| /// |
| /// A decoder returned from a request with require_can_re_sync is potentially |
| /// able to handle damaged input without closing the Codec channel. Such a |
| /// Codec is encouraged, but not required, to also satisfy requirements of |
| /// require_report_all_detected_errors. |
| // TODO(FIDL-609): Default to false. |
| 5: bool require_can_re_sync; |
| |
| /// Sometimes a client would rather fail an overall use of a decoder than fail |
| /// to notice data corruption. For such scenarios, the client can specify |
| /// require_report_all_detected_errors. For any codec returned from a |
| /// request with require_report_all_detected_errors set, on detection of |
| /// any input data corruption the codec will report in one or more of these |
| /// ways: |
| /// * closing the Codec channel |
| /// * OnStreamFailed() |
| /// * error_detected_before |
| /// * error_detected_during |
| /// |
| /// If false, a codec may silently skip past corrupted input data. |
| /// |
| /// No decoder can detect all corruption, because some corruption can look like |
| /// valid stream data. This requirement is only to request a codec that |
| /// is written to attempt to detect _and report_ input stream corruption. |
| /// |
| /// This flag is not intended to be 100% bulletproof. If a client needs robust |
| /// assurance that _all_ detectable stream corruption is _always_ detected, |
| /// this flag is not enough of a guarantee to achieve that. Since some stream |
| /// corruption is inherently non-detectable in any case, such a client should |
| /// consider using stronger techniques upstream to ensure that corruption can |
| /// be detected with the needed probability very close to 1. |
| /// |
| /// This flag being true doesn't imply anything about whether the codec will |
| /// discard damaged data vs. producing corresponding damaged output. Only that |
| /// the codec will set error_detected_* bools to true when appropriate. |
| /// |
| /// Regardless of this setting, not all timestamp_ish values provided on input |
| /// are guaranteed to show up on output. |
| // TODO(FIDL-609): Default to false. |
| 6: bool require_report_all_detected_errors; |
| |
| /// If true, require that the returned codec is HW-accelerated. |
| // TODO(FIDL-609): Default to false. |
| 7: bool require_hw; |
| |
| /// permit_lack_of_split_header_handling |
| /// |
| /// This field is a temporary field that will be going away. |
| /// |
| /// TODO(dustingreen): Remove this field once we're down to zero codecs with |
| /// problems handling split headers. |
| /// |
| /// By default, a Codec instance is required to handle "split headers", meaning |
| /// that a client is allowed to deliver parts of an AU one byte at a time, |
| /// including parts near the beginning of the AU, and the codec is required to |
| /// tolerate and handle that properly. However, unfortunately not all codecs |
| /// properly support split headers. If a client is willing to permit such a |
| /// codec to be used, the client can set this to true. Clients are not |
| /// encouraged to set this, but setting it may be necessary to find a codec for |
| /// some formats _for now_. If a client sets this to true, the client should |
| /// deliver data of each AU with many contiguous non-split bytes from the start |
| /// of each AU. The client is not strictly required to deliver one AU at a |
| /// time, only to ensure that either all the AU bytes are in a single packet or |
| /// that many bytes at the start of each AU are in a single packet. |
| /// |
| /// The specification for how a client should use this and how a client should |
| /// behave if setting this to true is intentionally vague, because lack of |
| /// support for header splitting is not ideal, and is expected to be |
| /// temporary, and all codecs should handle split headers in the long run. |
| /// The main intent of this field is to avoid giving an innocent client using |
| /// default value of false here a codec that can't properly handle split |
| /// headers. This is not an attempt at a mechanism to fully work around a |
| /// codec that doesn't handle split headers. |
| // TODO(dustingreen): In the near term, wire this up so that SoftAAC2.cpp |
| // used for ADTS is not selected when this field is false, even if there is |
| // no other suitable codec. In the long term, fix or work around the header |
| // handling behavior of SoftAAC2 when used in ADTS mode (and any other |
| // similar issues in other codecs) and remove this field. |
| // TODO(FIDL-609): Default to false. |
| 8: bool permit_lack_of_split_header_handling; |
| |
| /// If set to ON, the decoder must support secure buffers on output, and |
| /// must reject non-secure buffers on output. |
| /// |
| /// If set to OFF or not set, the created decoder will reject secure buffers |
| /// on output by closing the StreamProcessor channel. |
| /// |
| /// If secure_input_mode ON, secure_output_mode must also be ON. |
| 9: SecureMemoryMode secure_output_mode; |
| |
| /// If set to ON, the decoder must support secure buffers on input and must |
| /// reject non-secure buffers on input. |
| /// |
| /// If set to OFF or not set, the created decoder will reject secure buffers |
| /// on input by closing the StreamProcessor channel. |
| /// |
| /// If secure_input_mode ON, secure_output_mode must also be ON. |
| 10: SecureMemoryMode secure_input_mode; |
| }; |
| |
| /// Parameters used to request an encoder. |
| table CreateEncoder_Params { |
| /// The format of the uncompressed input data. |
| /// |
| /// This field should be a raw mime_type (e.g. 'video/raw') and uncompressed |
| /// format details for the encoder to use when reading buffers. |
| /// |
| /// To be elibigible an encoder must support the input format. |
| 1: fuchsia.media.FormatDetails input_details; |
| |
| /// If true, require that the returned codec is HW-accelerated. |
| // TODO(FIDL-609): Default to false. |
| 2: bool require_hw; |
| }; |
| |
| enum CodecType { |
| DECODER = 0; |
| ENCODER = 1; |
| }; |
| |
| struct CodecDescription { |
| // Decoder or encoder. |
| CodecType codec_type; |
| // The mime type of the compressed format. For decoders this is the mime |
| // type of the input. For encoders, this is the mime type of the output. |
| string mime_type; |
| |
| // TODO(dustingreen): All these fields should be optional. |
| // |
| // TODO(dustingreen): Re-evaluate this for encoders. |
| // |
| // For each of these fields, the default is the most-capable setting, but if a |
| // codec doesn't support the most-capable behavior, then the codec must |
| // override the default. |
| bool can_stream_bytes_input = true; |
| bool can_find_start = true; |
| bool can_re_sync = true; |
| bool will_report_all_detected_errors = true; |
| bool is_hw = true; |
| bool split_header_handling = true; |
| }; |
| |
| // CodecFactory |
| // |
| // The purpose of the media::CodecFactory interface is to create media::Codec |
| // instances. |
| // |
| // The interface methods don't attempt to homogenize all codec types, preferring |
| // to have a separate dedicated message for decoders. TBD whether calls for |
| // creating encoders will split up audio vs. video encoders, or be combined. |
| // |
| |
| // Each create request is self-contained, in the sense that the interface is not |
| // stateful between create requests. |
| [Discoverable] |
| protocol CodecFactory { |
| // Driver-based local CodecFactory(s) will send this once shortly after the |
| // main CodecFactory connects to the driver-local CodecFactory. |
| // |
| // For now, the main CodecFactory will not send this. |
| // |
| // A SW-based local CodecFactory(s) will not send this event. |
| // |
| // Each codec in the list must be separately-described, for clean aggregation. |
| -> OnCodecList(vector<CodecDescription> codecs); |
| |
| // Rough sequence to create a decoder: |
| // |
| // factory = ConnectToEnvironmentService(CodecFactory); |
| // CreateDecoder_Params params; |
| // [fill out params] |
| // CreateDecoder(params, decoder_request); |
| // |
| // See use_media_decoder code for more detail. |
| // |
| // TODO(dustingreen): More detail in this comment block. |
| |
| // Requests: |
| |
| // CreateDecoder: |
| // |
| // decoder_params - See CreateDecoder_Params comments for required |
| // and optional parameters for creating a decoder. |
| // |
| // decoder - a Codec.NewRequest() which will hopefully be connected to |
| // a Codec server, or the Codec channel will get closed if no suitable codec |
| // can be found. We don't return any additional Codec-specific status here |
| // because finding the Codec is allowed to be fully async, so we don't |
| // necessarily yet know on return from this method which Codec will be |
| // selected, if any. |
| CreateDecoder( |
| CreateDecoder_Params decoder_params, |
| request<fuchsia.media.StreamProcessor> decoder); |
| |
| // CreateEncoder: |
| // |
| // encoder_params - See CreateEncoder_Params comments for required |
| // and optional parameters for creating a decoder. |
| // |
| // encoder - a Codec.NewRequest() which will hopefully be connected to |
| // a Codec server, or the Codec channel will get closed if no suitable codec |
| // can be found. We don't return any additional Codec-specific status here |
| // because finding the Codec is allowed to be fully async, so we don't |
| // necessarily yet know on return from this method which Codec will be |
| // selected, if any. |
| CreateEncoder(CreateEncoder_Params encoder_params, |
| request<fuchsia.media.StreamProcessor> encoder); |
| }; |