// 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; // 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: // audio/aac // input_details.codec_oob_bytes must be an AudioSpecificConfig() as defined // by AAC spec. // audio/aac-adts // On a temporary basis, input_details.codec_oob_bytes must be an // AudioSpecificConfig() extracted from the ADTS stream data by the client. // This is temporary. Later, codec_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. CodecFormatDetails 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 timstamp_ish values provided on input // are guaranteed to show up on ouput. 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; }; 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. 1: -> 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. 2: CreateDecoder( CreateDecoder_Params decoder_params, request<Codec> decoder); // TODO(dustingreen): // CreateAudioEncoder // CreateVideoEncoder // (or combined) };