X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=quicksync_encoder.cpp;h=001901873b7fd641a43183f0c7a2b15b45e46ed8;hb=ab03e5e6f24b1651b4ca7df95e20aa5786939209;hp=5ebd454edfdb635ba630123c92adf4e68486830c;hpb=4b286cabe961c426ce340a85167346012691d711;p=nageru diff --git a/quicksync_encoder.cpp b/quicksync_encoder.cpp index 5ebd454..0019018 100644 --- a/quicksync_encoder.cpp +++ b/quicksync_encoder.cpp @@ -194,12 +194,17 @@ FrameReorderer::Frame FrameReorderer::get_first_frame() class QuickSyncEncoderImpl { public: - QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); + QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, AVOutputFormat *oformat, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder); ~QuickSyncEncoderImpl(); void add_audio(int64_t pts, vector audio); bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex); RefCountedGLsync end_frame(int64_t pts, int64_t duration, const vector &input_frames); void shutdown(); + void release_gl_resources(); + void set_stream_mux(Mux *mux) + { + stream_mux = mux; + } private: struct storage_task { @@ -247,11 +252,12 @@ private: VADisplay va_open_display(const string &va_display); void va_close_display(VADisplay va_dpy); int setup_encode(); - int release_encode(); + void release_encode(); void update_ReferenceFrames(int frame_type); int update_RefPicList(int frame_type); bool is_shutdown = false; + bool has_released_gl_resources = false; bool use_zerocopy; int drm_fd = -1; @@ -280,7 +286,7 @@ private: unique_ptr reorderer; X264Encoder *x264_encoder; // nullptr if not using x264. - Mux* stream_mux; // To HTTP. + Mux* stream_mux = nullptr; // To HTTP. unique_ptr file_mux; // To local disk. Display *x11_display = nullptr; @@ -1691,13 +1697,26 @@ void QuickSyncEncoderImpl::storage_task_thread() } } -int QuickSyncEncoderImpl::release_encode() +void QuickSyncEncoderImpl::release_encode() { for (unsigned i = 0; i < SURFACE_NUM; i++) { vaDestroyBuffer(va_dpy, gl_surfaces[i].coded_buf); vaDestroySurfaces(va_dpy, &gl_surfaces[i].src_surface, 1); vaDestroySurfaces(va_dpy, &gl_surfaces[i].ref_surface, 1); + } + + vaDestroyContext(va_dpy, context_id); + vaDestroyConfig(va_dpy, config_id); +} +void QuickSyncEncoderImpl::release_gl_resources() +{ + assert(is_shutdown); + if (has_released_gl_resources) { + return; + } + + for (unsigned i = 0; i < SURFACE_NUM; i++) { if (!use_zerocopy) { glBindBuffer(GL_PIXEL_PACK_BUFFER, gl_surfaces[i].pbo); glUnmapBuffer(GL_PIXEL_PACK_BUFFER); @@ -1708,10 +1727,7 @@ int QuickSyncEncoderImpl::release_encode() resource_pool->release_2d_texture(gl_surfaces[i].cbcr_tex); } - vaDestroyContext(va_dpy, context_id); - vaDestroyConfig(va_dpy, config_id); - - return 0; + has_released_gl_resources = true; } int QuickSyncEncoderImpl::deinit_va() @@ -1727,10 +1743,10 @@ namespace { } // namespace -QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) - : current_storage_frame(0), resource_pool(resource_pool), surface(surface), stream_audio_encoder(stream_audio_encoder), x264_encoder(x264_encoder), stream_mux(stream_mux), frame_width(width), frame_height(height) +QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, AVOutputFormat *oformat, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) + : current_storage_frame(0), resource_pool(resource_pool), surface(surface), stream_audio_encoder(stream_audio_encoder), x264_encoder(x264_encoder), frame_width(width), frame_height(height) { - file_audio_encoder.reset(new AudioEncoder(AUDIO_OUTPUT_CODEC_NAME, DEFAULT_AUDIO_OUTPUT_BIT_RATE)); + file_audio_encoder.reset(new AudioEncoder(AUDIO_OUTPUT_CODEC_NAME, DEFAULT_AUDIO_OUTPUT_BIT_RATE, oformat)); open_output_file(filename); file_audio_encoder->add_mux(file_mux.get()); @@ -1778,6 +1794,7 @@ QuickSyncEncoderImpl::QuickSyncEncoderImpl(const std::string &filename, movit::R QuickSyncEncoderImpl::~QuickSyncEncoderImpl() { shutdown(); + release_gl_resources(); } bool QuickSyncEncoderImpl::begin_frame(GLuint *y_tex, GLuint *cbcr_tex) @@ -1949,7 +1966,8 @@ void QuickSyncEncoderImpl::open_output_file(const std::string &filename) exit(1); } - file_mux.reset(new Mux(avctx, frame_width, frame_height, Mux::CODEC_H264, file_audio_encoder->get_codec(), TIMEBASE, DEFAULT_AUDIO_OUTPUT_BIT_RATE, nullptr)); + string video_extradata = ""; // FIXME: See other comment about global headers. + file_mux.reset(new Mux(avctx, frame_width, frame_height, Mux::CODEC_H264, video_extradata, file_audio_encoder->get_ctx(), TIMEBASE, nullptr)); } void QuickSyncEncoderImpl::encode_thread_func() @@ -2141,6 +2159,9 @@ void QuickSyncEncoderImpl::encode_frame(QuickSyncEncoderImpl::PendingFrame frame CHECK_VASTATUS(va_status, "vaBeginPicture"); if (frame_type == FRAME_IDR) { + // FIXME: If the mux wants global headers, we should not put the + // SPS/PPS before each IDR frame, but rather put it into the + // codec extradata (formatted differently?). render_sequence(); render_picture(frame_type, display_frame_num, gop_start_display_frame_num); if (h264_packedheader) { @@ -2170,8 +2191,8 @@ void QuickSyncEncoderImpl::encode_frame(QuickSyncEncoderImpl::PendingFrame frame } // Proxy object. -QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, Mux *stream_mux, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) - : impl(new QuickSyncEncoderImpl(filename, resource_pool, surface, va_display, width, height, stream_mux, stream_audio_encoder, x264_encoder)) {} +QuickSyncEncoder::QuickSyncEncoder(const std::string &filename, movit::ResourcePool *resource_pool, QSurface *surface, const string &va_display, int width, int height, AVOutputFormat *oformat, AudioEncoder *stream_audio_encoder, X264Encoder *x264_encoder) + : impl(new QuickSyncEncoderImpl(filename, resource_pool, surface, va_display, width, height, oformat, stream_audio_encoder, x264_encoder)) {} // Must be defined here because unique_ptr<> destructor needs to know the impl. QuickSyncEncoder::~QuickSyncEncoder() {} @@ -2195,3 +2216,9 @@ void QuickSyncEncoder::shutdown() { impl->shutdown(); } + +void QuickSyncEncoder::set_stream_mux(Mux *mux) +{ + impl->set_stream_mux(mux); +} +