summaryrefslogtreecommitdiff
path: root/chromium/media/ffmpeg/ffmpeg_decoding_loop.h
blob: ac51a739158ceade660a9483f78af2a04947c6b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 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 <memory>

#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<bool(AVFrame* frame)>;

  // 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<AVFrame, ScopedPtrAVFreeFrame> frame_;
  int last_averror_code_ = 0;

  DISALLOW_COPY_AND_ASSIGN(FFmpegDecodingLoop);
};

}  // namespace media

#endif  // MEDIA_FFMPEG_FFMPEG_DECODING_LOOP_H_