| // 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). |
| // |
| // TODO(dustingreen): Switch this to a FIDL table instead when possible. |
| struct 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/aac-adts |
| // On a temporary basis, input_details.oob_bytes must be an |
| // AudioSpecificConfig() extracted from the ADTS stream data by the client. |
| // This is temporary. Later, oob_bytes will be ignored and allowed to |
| // be null. On a temporary basis, see |
| // make_AudioSpecificConfig_from_ADTS_header() for some self-contained |
| // conversion code. |
| // TODO(dustingreen): fix this up server side and make most of this |
| // paragraph go away, possibly by also parsing ADTS before it hits OMX |
| // since the parsing code there doesn't tolerate split ADTS headers. |
| 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. |
| bool promise_separate_access_units_on_input = false; |
| |
| // "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. |
| bool require_can_stream_bytes_input = false; |
| |
| // 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. |
| bool require_can_find_start = false; |
| |
| // 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. |
| bool require_can_re_sync = false; |
| |
| // 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. |
| bool require_report_all_detected_errors = false; |
| |
| // If true, require that the returned codec is HW-accelerated. |
| bool require_hw = false; |
| |
| // 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. |
| bool permit_lack_of_split_header_handling = false; |
| }; |
| |
| /// Parameters used to request an encoder. |
| struct 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. |
| fuchsia.media.FormatDetails input_format; |
| |
| /// The desired format of the encoded output data. |
| /// |
| /// To be eligible an encoder must support the output mime_type and any |
| /// compressed format details. |
| fuchsia.media.FormatDetails output_format; |
| |
| /// If true, require that the returned codec is HW-accelerated. |
| bool require_hw = false; |
| }; |
| |
| 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] |
| interface 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); |
| }; |