// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CHROMEOS_CAMERA_MJPEG_DECODE_ACCELERATOR_H_
#define COMPONENTS_CHROMEOS_CAMERA_MJPEG_DECODE_ACCELERATOR_H_
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include "base/files/scoped_file.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "media/base/bitstream_buffer.h"
namespace media {
class VideoFrame;
}
namespace chromeos_camera {
// MJPEG decoder interface.
// The input are JPEG images including headers (Huffman tables may be omitted).
// The decoder will convert to the output color format if the input color format
// or subsampling does not match that and if it is capable of doing so. The
// client is responsible for allocating buffers and keeps the ownership of them.
// The intended use case of this interface is decoding MJPEG images coming
// from camera capture. It can also be used for normal still JPEG image
// decoding, but normal JPEG images may use more JPEG features that may not be
// supported by a particular accelerator implementation and/or platform.
class MjpegDecodeAccelerator {
public:
// Callback for JPEG decoder initialization.
typedef base::OnceCallback<void(bool success)> InitCB;
static const int32_t kInvalidTaskId = -1;
// Enumeration of decode errors generated by NotifyError callback. These
// values are persisted to logs. Entries should not be renumbered and numeric
// values should never be reused.
enum Error {
// No error. Decode succeeded.
NO_ERRORS = 0,
// Invalid argument was passed to an API method, e.g. the output buffer is
// too small, JPEG width/height are too big for JDA.
INVALID_ARGUMENT = 1,
// Encoded input is unreadable, e.g. failed to map on another process.
UNREADABLE_INPUT = 2,
// Failed to parse compressed JPEG picture.
PARSE_JPEG_FAILED = 3,
// Failed to decode JPEG due to unsupported JPEG features, such as profiles,
// coding mode, or color formats.
UNSUPPORTED_JPEG = 4,
// A fatal failure occurred in the GPU process layer or one of its
// dependencies. Examples of such failures include hardware failures,
// driver failures, library failures, browser programming errors, and so
// on. Client is responsible for destroying JDA after receiving this.
PLATFORM_FAILURE = 5,
// Largest used enum. This should be adjusted when new errors are added.
MJDA_ERROR_CODE_MAX = PLATFORM_FAILURE,
};
class Client {
public:
// Callback called after each successful Decode().
// Parameters:
// |task_id| is the id passed to Decode() call.
virtual void VideoFrameReady(int32_t task_id) = 0;
// Callback to notify errors. Client is responsible for destroying JDA when
// receiving a fatal error, i.e. PLATFORM_FAILURE. For other errors, client
// is informed about the buffer that failed to decode and may continue
// using the same instance of JDA.
// Parameters:
// |error| is the error code.
// |task_id| is the id passed to Decode() call that resulted in the
// recoverable error. For PLATFORM_FAILURE, |task_id| may be
// |kInvalidTaskId| if the error was not related to any particular buffer
// being processed.
virtual void NotifyError(int32_t task_id, Error error) = 0;
protected:
virtual ~Client() {}
};
// Destroys the decoder: all pending inputs are dropped immediately. This
// call may asynchronously free system resources, but its client-visible
// effects are synchronous. After destructor returns, no more callbacks
// will be made on the client.
virtual ~MjpegDecodeAccelerator() = 0;
// Initializes the MJPEG decoder. Should be called once per decoder
// construction. This call is asynchronous and executes |init_cb| upon
// completion. Parameters:
// |client| is the Client interface for decode callback. The provided
// pointer must be valid until destructor is called.
// |init_cb| is the MJPEG decoder initialization status report callback.
//
// |init_cb| is called on the same thread as InitializeAsync() and can
// potentially be called even after the MjpegDecodeAccelerator destructor.
virtual void InitializeAsync(Client* client, InitCB init_cb) {}
// Decodes the given bitstream buffer that contains one JPEG frame. It
// supports at least baseline encoding defined in JPEG ISO/IEC 10918-1. The
// decoder will convert the output to |video_frame->format()| or return
// PLATFORM_FAILURE if it cannot convert.
// Parameters:
// |bitstream_buffer| contains encoded JPEG frame.
// |video_frame| contains an allocated video frame for the output, backed
// with an UnsafeSharedMemoryRegion or DMA buffer.
//
// Client is responsible for filling the |video_frame->coded_size()|,
// |video_frame->visible_rect()|, and allocating its backing buffer. For
// unsafe shared memory backed VideoFrames, I420 and NV12 formats are
// supported. For DMA-buf backed VideoFrames, the supported formats depend on
// the underlying hardware implementation. After decode completes, the
// decoded JPEG frame will be filled into the |video_frame|. Ownership of the
// |bitstream_buffer| and |video_frame| remains with the client. The client
// is not allowed to deallocate them before VideoFrameReady or NotifyError()
// is invoked for given id of |bitstream_buffer|, or destructor returns.
virtual void Decode(media::BitstreamBuffer bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame) = 0;
// The same as above but the JPEG image is stored in a DMA buffer.
// Parameters:
// |src_dmabuf_fd| contains encoded JPEG frame.
// |src_size| is the size of the JPEG frame.
// |src_offset| is the offset at which the JPEG data starts.
// |dst_frame| contains an allocated video frame for the output, backed with
// an UnsafeSharedMemoryRegion or DMA buffer.
virtual void Decode(int32_t task_id,
base::ScopedFD src_dmabuf_fd,
size_t src_size,
off_t src_offset,
scoped_refptr<media::VideoFrame> dst_frame) = 0;
// Returns true when the JPEG decoder is supported. This can be called before
// Initialize().
virtual bool IsSupported() = 0;
};
} // namespace chromeos_camera
#endif // COMPONENTS_CHROMEOS_CAMERA_MJPEG_DECODE_ACCELERATOR_H_