• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkVideEncoder_DEFINED
9 #define SkVideEncoder_DEFINED
10 
11 #include "include/core/SkImage.h"
12 #include "include/core/SkStream.h"
13 
14 extern "C" {
15 #include "libavcodec/avcodec.h"
16 #include "libavformat/avformat.h"
17 #include "libavformat/avio.h"
18 #include "libavutil/pixdesc.h"
19 }
20 
21 // private to the impl
22 class SkRandomAccessWStream;
23 struct SwsContext;
24 
25 class SkVideoEncoder {
26 public:
27     SkVideoEncoder();
28     ~SkVideoEncoder();
29 
30     /**
31      *  Begina a new recording. Balance this (after adding all of your frames) with a call
32      *  to endRecording().
33      */
34     bool beginRecording(SkISize, int fps);
35 
36     /**
37      *  Returns the preferred ImageInfo for this recording. Only valid if beginRecording() has
38      *  been called, and endRecording has not been called (yet).
39      */
preferredInfo()40     SkImageInfo preferredInfo() const { return fInfo; }
41 
42     /**
43      *  If you have your own pixmap, call addFrame(). Note this may fail if it uses an unsupported
44      *  ColorType or AlphaType, or the dimensions don't match those set in beginRecording.
45      *  For best results, use the SkImageInfo returned by preferredInfo().
46      */
47     bool addFrame(const SkPixmap&);
48 
49     /**
50      *  As an alternative to calling addFrame(), you can call beginFrame/endFrame, and the encoder
51      *  will manage allocating a surface/canvas for you.
52      *
53      *  SkCanvas* canvas = encoder.beginFrame();
54      *  // your drawing code here, drawing into canvas
55      *  encoder.endFrame();
56      */
57     SkCanvas* beginFrame();
58     bool endFrame();
59 
60     /**
61      *  Call this after having added all of your frames. After calling this, no more frames can
62      *  be added to this recording. To record a new video, call beginRecording().
63      */
64     sk_sp<SkData> endRecording();
65 
66 private:
67     void reset();
68     bool init(int fps);
69     bool sendFrame(AVFrame*);   // frame can be null
70 
71     double computeTimeStamp(const AVFrame*) const;
72 
73     SwsContext*     fSWScaleCtx = nullptr;
74     AVIOContext*    fStreamCtx = nullptr;
75     AVFormatContext* fFormatCtx = nullptr;
76     AVCodecContext* fEncoderCtx = nullptr;
77     AVStream*       fStream = nullptr;  // we do not free this
78     AVFrame*        fFrame = nullptr;
79     AVPacket*       fPacket = nullptr;
80 
81     SkImageInfo     fInfo;  // only defined between beginRecording() and endRecording()
82     std::unique_ptr<SkRandomAccessWStream> fWStream;
83     int64_t         fCurrentPTS, fDeltaPTS;
84 
85     // Lazily allocated, iff the client has called beginFrame() for a given recording session.
86     sk_sp<SkSurface> fSurface;
87 
88 };
89 
90 #endif
91 
92