// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef MEDIA_FFMPEG_FFMPEG_DECODING_LOOP_H_ #define MEDIA_FFMPEG_FFMPEG_DECODING_LOOP_H_ #include #include "base/callback_forward.h" #include "base/macros.h" #include "media/base/media_export.h" #include "media/ffmpeg/ffmpeg_deleters.h" struct AVCodecContext; struct AVFrame; struct AVPacket; namespace media { class MEDIA_EXPORT FFmpegDecodingLoop { public: enum class DecodeStatus { // Everything went just okay. kOkay, // Indicates that avcodec_send_packet() failed on the current packet. This // error is fatal and indicates the decoding loop is no longer viable. kSendPacketFailed, // Indicates that avcodec_receive_frame() failed on some packet; it may be a // packet sent in the past. If |continue_on_decoding_errors| is true, this // code is recoverable and may be ignored. kDecodeFrameFailed, // Returned when FrameReadyCB returns false which indicates that an internal // error has occurred; will immediately stop the decoding loop. This should // not be considered recoverable since internal loop state is unknown. kFrameProcessingFailed, }; // Creates a decoding loop using the already initialized codec |context|. If // decoding errors should be non-fatal, set |continue_on_decoding_errors| to // true; note: send packet failures are always fatal. FFmpegDecodingLoop(AVCodecContext* context, bool continue_on_decoding_errors = false); ~FFmpegDecodingLoop(); // Callback issued when the decoding loop has produced a frame. |frame| is // owned by the decoding loop. Return true to continue the decoding loop. using FrameReadyCB = base::RepeatingCallback; // Spins a generic decoding which decodes all available frames and sends them // to |frame_ready_cb| given a single input |packet|. Returns an enum with // success or the appropriate error code if failure. // // If |packet| is an end of stream packet all available frames still in the // decoder will be returned. After end of stream, |context| will not be usable // for decoding until avcodec_flush_buffers() is called on the context; which // the decoding loop does not handle. DecodeStatus DecodePacket(const AVPacket* packet, FrameReadyCB frame_ready_cb); int last_averror_code() const { return last_averror_code_; } private: const bool continue_on_decoding_errors_; AVCodecContext* const context_; std::unique_ptr frame_; int last_averror_code_ = 0; DISALLOW_COPY_AND_ASSIGN(FFmpegDecodingLoop); }; } // namespace media #endif // MEDIA_FFMPEG_FFMPEG_DECODING_LOOP_H_