]> git.sesse.net Git - nageru/blob - h264encode.h
If we have waiting B-frames at the end of the encode, encode them as such.
[nageru] / h264encode.h
1 // Hardware H.264 encoding via VAAPI. Heavily modified based on example
2 // code by Intel. Intel's original copyright and license is reproduced below:
3 //
4 // Copyright (c) 2007-2013 Intel Corporation. All Rights Reserved.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a
7 // copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sub license, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 // 
14 // The above copyright notice and this permission notice (including the
15 // next paragraph) shall be included in all copies or substantial portions
16 // of the Software.
17 // 
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 // IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 #ifndef _H264ENCODE_H
27 #define _H264ENCODE_H
28
29 extern "C" {
30 #include <libavcodec/avcodec.h>
31 #include <libavformat/avformat.h>
32 }
33 #include <epoxy/gl.h>
34 #include <stdbool.h>
35 #include <stdint.h>
36 #include <atomic>
37 #include <condition_variable>
38 #include <map>
39 #include <memory>
40 #include <mutex>
41 #include <queue>
42 #include <thread>
43 #include <vector>
44
45 #include "bmusb/bmusb.h"
46 #include "context.h"
47 #include "pbo_frame_allocator.h"
48 #include "ref_counted_frame.h"
49 #include "ref_counted_gl_sync.h"
50
51 class HTTPD;
52 class QSurface;
53
54 #define SURFACE_NUM 16 /* 16 surfaces for source YUV */
55
56 class H264Encoder {
57 public:
58         H264Encoder(QSurface *surface, int width, int height, HTTPD *httpd);
59         ~H264Encoder();
60         //void add_frame(FrameAllocator::Frame frame, GLsync fence);
61
62 #if 0
63         struct Frame {
64         public:
65                 GLuint fbo;
66                 GLuint y_tex, cbcr_tex; 
67
68         private:
69                 //int surface_subnum;
70         };
71         void 
72 #endif
73         void add_audio(int64_t pts, std::vector<float> audio);  // Needs to come before end_frame() of same pts.
74         bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex);
75         void end_frame(RefCountedGLsync fence, int64_t pts, const std::vector<RefCountedFrame> &input_frames);
76
77 private:
78         struct storage_task {
79                 unsigned long long display_order;
80                 int frame_type;
81                 std::vector<float> audio;
82                 int64_t pts, dts;
83         };
84         struct PendingFrame {
85                 RefCountedGLsync fence;
86                 std::vector<RefCountedFrame> input_frames;
87                 int64_t pts;
88         };
89
90         void encode_thread_func();
91         void encode_remaining_frames_as_p(int encoding_frame_num, int gop_start_display_frame_num, int64_t last_dts);
92         void encode_frame(PendingFrame frame, int encoding_frame_num, int display_frame_num, int gop_start_display_frame_num,
93                           int frame_type, int64_t pts, int64_t dts);
94         void storage_task_thread();
95         void storage_task_enqueue(storage_task task);
96         void save_codeddata(storage_task task);
97
98         std::thread encode_thread, storage_thread;
99
100         std::mutex storage_task_queue_mutex;
101         std::condition_variable storage_task_queue_changed;
102         int srcsurface_status[SURFACE_NUM];  // protected by storage_task_queue_mutex
103         std::queue<storage_task> storage_task_queue;  // protected by storage_task_queue_mutex
104         bool storage_thread_should_quit = false;  // protected by storage_task_queue_mutex
105
106         std::mutex frame_queue_mutex;
107         std::condition_variable frame_queue_nonempty;
108         bool encode_thread_should_quit = false;  // under frame_queue_mutex
109
110         //int frame_width, frame_height;
111         //int ;
112         int current_storage_frame;
113
114         std::map<int, PendingFrame> pending_video_frames;  // under frame_queue_mutex
115         std::map<int64_t, std::vector<float>> pending_audio_frames;  // under frame_queue_mutex
116         QSurface *surface;
117
118         AVCodecContext *context_audio;
119         HTTPD *httpd;
120 };
121
122 #endif