michael@0: /* michael@0: * Copyright (c) 2010 The WebM project authors. All Rights Reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: michael@0: /*!\file michael@0: * \brief Describes the decoder algorithm interface for algorithm michael@0: * implementations. michael@0: * michael@0: * This file defines the private structures and data types that are only michael@0: * relevant to implementing an algorithm, as opposed to using it. michael@0: * michael@0: * To create a decoder algorithm class, an interface structure is put michael@0: * into the global namespace: michael@0: *
michael@0:  *     my_codec.c:
michael@0:  *       vpx_codec_iface_t my_codec = {
michael@0:  *           "My Codec v1.0",
michael@0:  *           VPX_CODEC_ALG_ABI_VERSION,
michael@0:  *           ...
michael@0:  *       };
michael@0:  *     
michael@0: * michael@0: * An application instantiates a specific decoder instance by using michael@0: * vpx_codec_init() and a pointer to the algorithm's interface structure: michael@0: *
michael@0:  *     my_app.c:
michael@0:  *       extern vpx_codec_iface_t my_codec;
michael@0:  *       {
michael@0:  *           vpx_codec_ctx_t algo;
michael@0:  *           res = vpx_codec_init(&algo, &my_codec);
michael@0:  *       }
michael@0:  *     
michael@0: * michael@0: * Once initialized, the instance is manged using other functions from michael@0: * the vpx_codec_* family. michael@0: */ michael@0: #ifndef VPX_CODEC_INTERNAL_H michael@0: #define VPX_CODEC_INTERNAL_H michael@0: #include "../vpx_decoder.h" michael@0: #include "../vpx_encoder.h" michael@0: #include michael@0: michael@0: michael@0: /*!\brief Current ABI version number michael@0: * michael@0: * \internal michael@0: * If this file is altered in any way that changes the ABI, this value michael@0: * must be bumped. Examples include, but are not limited to, changing michael@0: * types, removing or reassigning enums, adding/removing/rearranging michael@0: * fields to structures michael@0: */ michael@0: #define VPX_CODEC_INTERNAL_ABI_VERSION (4) /**<\hideinitializer*/ michael@0: michael@0: typedef struct vpx_codec_alg_priv vpx_codec_alg_priv_t; michael@0: typedef struct vpx_codec_priv_enc_mr_cfg vpx_codec_priv_enc_mr_cfg_t; michael@0: michael@0: /*!\brief init function pointer prototype michael@0: * michael@0: * Performs algorithm-specific initialization of the decoder context. This michael@0: * function is called by the generic vpx_codec_init() wrapper function, so michael@0: * plugins implementing this interface may trust the input parameters to be michael@0: * properly initialized. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \retval #VPX_CODEC_OK michael@0: * The input stream was recognized and decoder initialized. michael@0: * \retval #VPX_CODEC_MEM_ERROR michael@0: * Memory operation failed. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_init_fn_t)(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_priv_enc_mr_cfg_t *data); michael@0: michael@0: /*!\brief destroy function pointer prototype michael@0: * michael@0: * Performs algorithm-specific destruction of the decoder context. This michael@0: * function is called by the generic vpx_codec_destroy() wrapper function, michael@0: * so plugins implementing this interface may trust the input parameters michael@0: * to be properly initialized. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \retval #VPX_CODEC_OK michael@0: * The input stream was recognized and decoder initialized. michael@0: * \retval #VPX_CODEC_MEM_ERROR michael@0: * Memory operation failed. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_destroy_fn_t)(vpx_codec_alg_priv_t *ctx); michael@0: michael@0: /*!\brief parse stream info function pointer prototype michael@0: * michael@0: * Performs high level parsing of the bitstream. This function is called by the michael@0: * generic vpx_codec_peek_stream_info() wrapper function, so plugins michael@0: * implementing this interface may trust the input parameters to be properly michael@0: * initialized. michael@0: * michael@0: * \param[in] data Pointer to a block of data to parse michael@0: * \param[in] data_sz Size of the data buffer michael@0: * \param[in,out] si Pointer to stream info to update. The size member michael@0: * \ref MUST be properly initialized, but \ref MAY be michael@0: * clobbered by the algorithm. This parameter \ref MAY michael@0: * be NULL. michael@0: * michael@0: * \retval #VPX_CODEC_OK michael@0: * Bitstream is parsable and stream information updated michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_peek_si_fn_t)(const uint8_t *data, michael@0: unsigned int data_sz, michael@0: vpx_codec_stream_info_t *si); michael@0: michael@0: /*!\brief Return information about the current stream. michael@0: * michael@0: * Returns information about the stream that has been parsed during decoding. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \param[in,out] si Pointer to stream info to update. The size member michael@0: * \ref MUST be properly initialized, but \ref MAY be michael@0: * clobbered by the algorithm. This parameter \ref MAY michael@0: * be NULL. michael@0: * michael@0: * \retval #VPX_CODEC_OK michael@0: * Bitstream is parsable and stream information updated michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_get_si_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: vpx_codec_stream_info_t *si); michael@0: michael@0: /*!\brief control function pointer prototype michael@0: * michael@0: * This function is used to exchange algorithm specific data with the decoder michael@0: * instance. This can be used to implement features specific to a particular michael@0: * algorithm. michael@0: * michael@0: * This function is called by the generic vpx_codec_control() wrapper michael@0: * function, so plugins implementing this interface may trust the input michael@0: * parameters to be properly initialized. However, this interface does not michael@0: * provide type safety for the exchanged data or assign meanings to the michael@0: * control codes. Those details should be specified in the algorithm's michael@0: * header file. In particular, the ctrl_id parameter is guaranteed to exist michael@0: * in the algorithm's control mapping table, and the data parameter may be NULL. michael@0: * michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \param[in] ctrl_id Algorithm specific control identifier michael@0: * \param[in,out] data Data to exchange with algorithm instance. michael@0: * michael@0: * \retval #VPX_CODEC_OK michael@0: * The internal state data was deserialized. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_control_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: int ctrl_id, michael@0: va_list ap); michael@0: michael@0: /*!\brief control function pointer mapping michael@0: * michael@0: * This structure stores the mapping between control identifiers and michael@0: * implementing functions. Each algorithm provides a list of these michael@0: * mappings. This list is searched by the vpx_codec_control() wrapper michael@0: * function to determine which function to invoke. The special michael@0: * value {0, NULL} is used to indicate end-of-list, and must be michael@0: * present. The special value {0, } can be used as a catch-all michael@0: * mapping. This implies that ctrl_id values chosen by the algorithm michael@0: * \ref MUST be non-zero. michael@0: */ michael@0: typedef const struct vpx_codec_ctrl_fn_map { michael@0: int ctrl_id; michael@0: vpx_codec_control_fn_t fn; michael@0: } vpx_codec_ctrl_fn_map_t; michael@0: michael@0: /*!\brief decode data function pointer prototype michael@0: * michael@0: * Processes a buffer of coded data. If the processing results in a new michael@0: * decoded frame becoming available, #VPX_CODEC_CB_PUT_SLICE and michael@0: * #VPX_CODEC_CB_PUT_FRAME events are generated as appropriate. This michael@0: * function is called by the generic vpx_codec_decode() wrapper function, michael@0: * so plugins implementing this interface may trust the input parameters michael@0: * to be properly initialized. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \param[in] data Pointer to this block of new coded data. If michael@0: * NULL, a #VPX_CODEC_CB_PUT_FRAME event is posted michael@0: * for the previously decoded frame. michael@0: * \param[in] data_sz Size of the coded data, in bytes. michael@0: * michael@0: * \return Returns #VPX_CODEC_OK if the coded data was processed completely michael@0: * and future pictures can be decoded without error. Otherwise, michael@0: * see the descriptions of the other error codes in ::vpx_codec_err_t michael@0: * for recoverability capabilities. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_decode_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: const uint8_t *data, michael@0: unsigned int data_sz, michael@0: void *user_priv, michael@0: long deadline); michael@0: michael@0: /*!\brief Decoded frames iterator michael@0: * michael@0: * Iterates over a list of the frames available for display. The iterator michael@0: * storage should be initialized to NULL to start the iteration. Iteration is michael@0: * complete when this function returns NULL. michael@0: * michael@0: * The list of available frames becomes valid upon completion of the michael@0: * vpx_codec_decode call, and remains valid until the next call to vpx_codec_decode. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \param[in out] iter Iterator storage, initialized to NULL michael@0: * michael@0: * \return Returns a pointer to an image, if one is ready for display. Frames michael@0: * produced will always be in PTS (presentation time stamp) order. michael@0: */ michael@0: typedef vpx_image_t *(*vpx_codec_get_frame_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: vpx_codec_iter_t *iter); michael@0: michael@0: michael@0: /*\brief eXternal Memory Allocation memory map get iterator michael@0: * michael@0: * Iterates over a list of the memory maps requested by the decoder. The michael@0: * iterator storage should be initialized to NULL to start the iteration. michael@0: * Iteration is complete when this function returns NULL. michael@0: * michael@0: * \param[in out] iter Iterator storage, initialized to NULL michael@0: * michael@0: * \return Returns a pointer to an memory segment descriptor, or NULL to michael@0: * indicate end-of-list. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_get_mmap_fn_t)(const vpx_codec_ctx_t *ctx, michael@0: vpx_codec_mmap_t *mmap, michael@0: vpx_codec_iter_t *iter); michael@0: michael@0: michael@0: /*\brief eXternal Memory Allocation memory map set iterator michael@0: * michael@0: * Sets a memory descriptor inside the decoder instance. michael@0: * michael@0: * \param[in] ctx Pointer to this instance's context michael@0: * \param[in] mmap Memory map to store. michael@0: * michael@0: * \retval #VPX_CODEC_OK michael@0: * The memory map was accepted and stored. michael@0: * \retval #VPX_CODEC_MEM_ERROR michael@0: * The memory map was rejected. michael@0: */ michael@0: typedef vpx_codec_err_t (*vpx_codec_set_mmap_fn_t)(vpx_codec_ctx_t *ctx, michael@0: const vpx_codec_mmap_t *mmap); michael@0: michael@0: michael@0: typedef vpx_codec_err_t (*vpx_codec_encode_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: const vpx_image_t *img, michael@0: vpx_codec_pts_t pts, michael@0: unsigned long duration, michael@0: vpx_enc_frame_flags_t flags, michael@0: unsigned long deadline); michael@0: typedef const vpx_codec_cx_pkt_t *(*vpx_codec_get_cx_data_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: vpx_codec_iter_t *iter); michael@0: michael@0: typedef vpx_codec_err_t michael@0: (*vpx_codec_enc_config_set_fn_t)(vpx_codec_alg_priv_t *ctx, michael@0: const vpx_codec_enc_cfg_t *cfg); michael@0: typedef vpx_fixed_buf_t * michael@0: (*vpx_codec_get_global_headers_fn_t)(vpx_codec_alg_priv_t *ctx); michael@0: michael@0: typedef vpx_image_t * michael@0: (*vpx_codec_get_preview_frame_fn_t)(vpx_codec_alg_priv_t *ctx); michael@0: michael@0: typedef vpx_codec_err_t michael@0: (*vpx_codec_enc_mr_get_mem_loc_fn_t)(const vpx_codec_enc_cfg_t *cfg, michael@0: void **mem_loc); michael@0: michael@0: /*!\brief usage configuration mapping michael@0: * michael@0: * This structure stores the mapping between usage identifiers and michael@0: * configuration structures. Each algorithm provides a list of these michael@0: * mappings. This list is searched by the vpx_codec_enc_config_default() michael@0: * wrapper function to determine which config to return. The special value michael@0: * {-1, {0}} is used to indicate end-of-list, and must be present. At least michael@0: * one mapping must be present, in addition to the end-of-list. michael@0: * michael@0: */ michael@0: typedef const struct vpx_codec_enc_cfg_map { michael@0: int usage; michael@0: vpx_codec_enc_cfg_t cfg; michael@0: } vpx_codec_enc_cfg_map_t; michael@0: michael@0: #define NOT_IMPLEMENTED 0 michael@0: michael@0: /*!\brief Decoder algorithm interface interface michael@0: * michael@0: * All decoders \ref MUST expose a variable of this type. michael@0: */ michael@0: struct vpx_codec_iface { michael@0: const char *name; /**< Identification String */ michael@0: int abi_version; /**< Implemented ABI version */ michael@0: vpx_codec_caps_t caps; /**< Decoder capabilities */ michael@0: vpx_codec_init_fn_t init; /**< \copydoc ::vpx_codec_init_fn_t */ michael@0: vpx_codec_destroy_fn_t destroy; /**< \copydoc ::vpx_codec_destroy_fn_t */ michael@0: vpx_codec_ctrl_fn_map_t *ctrl_maps; /**< \copydoc ::vpx_codec_ctrl_fn_map_t */ michael@0: vpx_codec_get_mmap_fn_t get_mmap; /**< \copydoc ::vpx_codec_get_mmap_fn_t */ michael@0: vpx_codec_set_mmap_fn_t set_mmap; /**< \copydoc ::vpx_codec_set_mmap_fn_t */ michael@0: struct vpx_codec_dec_iface { michael@0: vpx_codec_peek_si_fn_t peek_si; /**< \copydoc ::vpx_codec_peek_si_fn_t */ michael@0: vpx_codec_get_si_fn_t get_si; /**< \copydoc ::vpx_codec_get_si_fn_t */ michael@0: vpx_codec_decode_fn_t decode; /**< \copydoc ::vpx_codec_decode_fn_t */ michael@0: vpx_codec_get_frame_fn_t get_frame; /**< \copydoc ::vpx_codec_get_frame_fn_t */ michael@0: } dec; michael@0: struct vpx_codec_enc_iface { michael@0: vpx_codec_enc_cfg_map_t *cfg_maps; /**< \copydoc ::vpx_codec_enc_cfg_map_t */ michael@0: vpx_codec_encode_fn_t encode; /**< \copydoc ::vpx_codec_encode_fn_t */ michael@0: vpx_codec_get_cx_data_fn_t get_cx_data; /**< \copydoc ::vpx_codec_get_cx_data_fn_t */ michael@0: vpx_codec_enc_config_set_fn_t cfg_set; /**< \copydoc ::vpx_codec_enc_config_set_fn_t */ michael@0: vpx_codec_get_global_headers_fn_t get_glob_hdrs; /**< \copydoc ::vpx_codec_get_global_headers_fn_t */ michael@0: vpx_codec_get_preview_frame_fn_t get_preview; /**< \copydoc ::vpx_codec_get_preview_frame_fn_t */ michael@0: vpx_codec_enc_mr_get_mem_loc_fn_t mr_get_mem_loc; /**< \copydoc ::vpx_codec_enc_mr_get_mem_loc_fn_t */ michael@0: } enc; michael@0: }; michael@0: michael@0: /*!\brief Callback function pointer / user data pair storage */ michael@0: typedef struct vpx_codec_priv_cb_pair { michael@0: union { michael@0: vpx_codec_put_frame_cb_fn_t put_frame; michael@0: vpx_codec_put_slice_cb_fn_t put_slice; michael@0: } u; michael@0: void *user_priv; michael@0: } vpx_codec_priv_cb_pair_t; michael@0: michael@0: michael@0: /*!\brief Instance private storage michael@0: * michael@0: * This structure is allocated by the algorithm's init function. It can be michael@0: * extended in one of two ways. First, a second, algorithm specific structure michael@0: * can be allocated and the priv member pointed to it. Alternatively, this michael@0: * structure can be made the first member of the algorithm specific structure, michael@0: * and the pointer cast to the proper type. michael@0: */ michael@0: struct vpx_codec_priv { michael@0: unsigned int sz; michael@0: vpx_codec_iface_t *iface; michael@0: struct vpx_codec_alg_priv *alg_priv; michael@0: const char *err_detail; michael@0: vpx_codec_flags_t init_flags; michael@0: struct { michael@0: vpx_codec_priv_cb_pair_t put_frame_cb; michael@0: vpx_codec_priv_cb_pair_t put_slice_cb; michael@0: } dec; michael@0: struct { michael@0: int tbd; michael@0: struct vpx_fixed_buf cx_data_dst_buf; michael@0: unsigned int cx_data_pad_before; michael@0: unsigned int cx_data_pad_after; michael@0: vpx_codec_cx_pkt_t cx_data_pkt; michael@0: unsigned int total_encoders; michael@0: } enc; michael@0: }; michael@0: michael@0: /* michael@0: * Multi-resolution encoding internal configuration michael@0: */ michael@0: struct vpx_codec_priv_enc_mr_cfg michael@0: { michael@0: unsigned int mr_total_resolutions; michael@0: unsigned int mr_encoder_id; michael@0: struct vpx_rational mr_down_sampling_factor; michael@0: void* mr_low_res_mode_info; michael@0: }; michael@0: michael@0: #undef VPX_CTRL_USE_TYPE michael@0: #define VPX_CTRL_USE_TYPE(id, typ) \ michael@0: static typ id##__value(va_list args) {return va_arg(args, typ);} \ michael@0: static typ id##__convert(void *x)\ michael@0: {\ michael@0: union\ michael@0: {\ michael@0: void *x;\ michael@0: typ d;\ michael@0: } u;\ michael@0: u.x = x;\ michael@0: return u.d;\ michael@0: } michael@0: michael@0: michael@0: #undef VPX_CTRL_USE_TYPE_DEPRECATED michael@0: #define VPX_CTRL_USE_TYPE_DEPRECATED(id, typ) \ michael@0: static typ id##__value(va_list args) {return va_arg(args, typ);} \ michael@0: static typ id##__convert(void *x)\ michael@0: {\ michael@0: union\ michael@0: {\ michael@0: void *x;\ michael@0: typ d;\ michael@0: } u;\ michael@0: u.x = x;\ michael@0: return u.d;\ michael@0: } michael@0: michael@0: #define CAST(id, arg) id##__value(arg) michael@0: #define RECAST(id, x) id##__convert(x) michael@0: michael@0: michael@0: /* CODEC_INTERFACE convenience macro michael@0: * michael@0: * By convention, each codec interface is a struct with extern linkage, where michael@0: * the symbol is suffixed with _algo. A getter function is also defined to michael@0: * return a pointer to the struct, since in some cases it's easier to work michael@0: * with text symbols than data symbols (see issue #169). This function has michael@0: * the same name as the struct, less the _algo suffix. The CODEC_INTERFACE michael@0: * macro is provided to define this getter function automatically. michael@0: */ michael@0: #define CODEC_INTERFACE(id)\ michael@0: vpx_codec_iface_t* id(void) { return &id##_algo; }\ michael@0: vpx_codec_iface_t id##_algo michael@0: michael@0: michael@0: /* Internal Utility Functions michael@0: * michael@0: * The following functions are intended to be used inside algorithms as michael@0: * utilities for manipulating vpx_codec_* data structures. michael@0: */ michael@0: struct vpx_codec_pkt_list { michael@0: unsigned int cnt; michael@0: unsigned int max; michael@0: struct vpx_codec_cx_pkt pkts[1]; michael@0: }; michael@0: michael@0: #define vpx_codec_pkt_list_decl(n)\ michael@0: union {struct vpx_codec_pkt_list head;\ michael@0: struct {struct vpx_codec_pkt_list head;\ michael@0: struct vpx_codec_cx_pkt pkts[n];} alloc;} michael@0: michael@0: #define vpx_codec_pkt_list_init(m)\ michael@0: (m)->alloc.head.cnt = 0,\ michael@0: (m)->alloc.head.max = sizeof((m)->alloc.pkts) / sizeof((m)->alloc.pkts[0]) michael@0: michael@0: int michael@0: vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *, michael@0: const struct vpx_codec_cx_pkt *); michael@0: michael@0: const vpx_codec_cx_pkt_t * michael@0: vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list, michael@0: vpx_codec_iter_t *iter); michael@0: michael@0: michael@0: #include michael@0: #include michael@0: struct vpx_internal_error_info { michael@0: vpx_codec_err_t error_code; michael@0: int has_detail; michael@0: char detail[80]; michael@0: int setjmp; michael@0: jmp_buf jmp; michael@0: }; michael@0: michael@0: static void vpx_internal_error(struct vpx_internal_error_info *info, michael@0: vpx_codec_err_t error, michael@0: const char *fmt, michael@0: ...) { michael@0: va_list ap; michael@0: michael@0: info->error_code = error; michael@0: info->has_detail = 0; michael@0: michael@0: if (fmt) { michael@0: size_t sz = sizeof(info->detail); michael@0: michael@0: info->has_detail = 1; michael@0: va_start(ap, fmt); michael@0: vsnprintf(info->detail, sz - 1, fmt, ap); michael@0: va_end(ap); michael@0: info->detail[sz - 1] = '\0'; michael@0: } michael@0: michael@0: if (info->setjmp) michael@0: longjmp(info->jmp, info->error_code); michael@0: } michael@0: michael@0: //------------------------------------------------------------------------------ michael@0: // mmap interface michael@0: michael@0: typedef struct { michael@0: unsigned int id; michael@0: unsigned long sz; michael@0: unsigned int align; michael@0: unsigned int flags; michael@0: unsigned long (*calc_sz)(const vpx_codec_dec_cfg_t *, vpx_codec_flags_t); michael@0: } mem_req_t; michael@0: michael@0: // Allocates mmap.priv and sets mmap.base based on mmap.sz/align/flags michael@0: // requirements. michael@0: // Returns #VPX_CODEC_OK on success, #VPX_CODEC_MEM_ERROR otherwise. michael@0: vpx_codec_err_t vpx_mmap_alloc(vpx_codec_mmap_t *mmap); michael@0: michael@0: // Frees mmap.base allocated by a call to vpx_mmap_alloc(). michael@0: void vpx_mmap_dtor(vpx_codec_mmap_t *mmap); michael@0: michael@0: // Checks each mmap has the size requirement specificied by mem_reqs. michael@0: // Returns #VPX_CODEC_OK on success, #VPX_CODEC_MEM_ERROR otherwise. michael@0: vpx_codec_err_t vpx_validate_mmaps(const vpx_codec_stream_info_t *si, michael@0: const vpx_codec_mmap_t *mmaps, michael@0: const mem_req_t *mem_reqs, int nreqs, michael@0: vpx_codec_flags_t init_flags); michael@0: #endif