]> git.sesse.net Git - nageru/blobdiff - video_encoder.cpp
Add support for ALSA devices that have no channel maps.
[nageru] / video_encoder.cpp
index 7719bbbc15c86d1ce2890a64e4117f7935c85a77..dfbf565437d5dcfc311f84c7245eaa06eaee68be 100644 (file)
@@ -35,8 +35,8 @@ string generate_local_dump_filename(int frame)
 
 }  // namespace
 
-VideoEncoder::VideoEncoder(ResourcePool *resource_pool, QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd)
-       : resource_pool(resource_pool), surface(surface), va_display(va_display), width(width), height(height), httpd(httpd)
+VideoEncoder::VideoEncoder(ResourcePool *resource_pool, QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd, DiskSpaceEstimator *disk_space_estimator)
+       : resource_pool(resource_pool), surface(surface), va_display(va_display), width(width), height(height), httpd(httpd), disk_space_estimator(disk_space_estimator)
 {
        oformat = av_guess_format(global_flags.stream_mux_name.c_str(), nullptr, nullptr);
        assert(oformat != nullptr);
@@ -50,12 +50,14 @@ VideoEncoder::VideoEncoder(ResourcePool *resource_pool, QSurface *surface, const
        }
 
        string filename = generate_local_dump_filename(/*frame=*/0);
-       quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, oformat, stream_audio_encoder.get(), x264_encoder.get()));
+       quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, oformat, x264_encoder.get(), disk_space_estimator));
 
        open_output_stream();
        stream_audio_encoder->add_mux(stream_mux.get());
        quicksync_encoder->set_stream_mux(stream_mux.get());
-       x264_encoder->set_mux(stream_mux.get());
+       if (global_flags.x264_video_to_http) {
+               x264_encoder->set_mux(stream_mux.get());
+       }
 }
 
 VideoEncoder::~VideoEncoder()
@@ -90,14 +92,20 @@ void VideoEncoder::do_cut(int frame)
                qs_needing_cleanup.emplace_back(old_encoder);
        }).detach();
 
-       quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, oformat, stream_audio_encoder.get(), x264_encoder.get()));
+       quicksync_encoder.reset(new QuickSyncEncoder(filename, resource_pool, surface, va_display, width, height, oformat, x264_encoder.get(), disk_space_estimator));
        quicksync_encoder->set_stream_mux(stream_mux.get());
 }
 
+void VideoEncoder::change_x264_bitrate(unsigned rate_kbit)
+{
+       x264_encoder->change_bitrate(rate_kbit);
+}
+
 void VideoEncoder::add_audio(int64_t pts, std::vector<float> audio)
 {
        lock_guard<mutex> lock(qs_mu);
        quicksync_encoder->add_audio(pts, audio);
+       stream_audio_encoder->encode_audio(audio, pts + quicksync_encoder->global_delay());
 }
 
 bool VideoEncoder::begin_frame(GLuint *y_tex, GLuint *cbcr_tex)
@@ -119,7 +127,9 @@ void VideoEncoder::open_output_stream()
        avctx->oformat = oformat;
 
        uint8_t *buf = (uint8_t *)av_malloc(MUX_BUFFER_SIZE);
-       avctx->pb = avio_alloc_context(buf, MUX_BUFFER_SIZE, 1, this, nullptr, &VideoEncoder::write_packet_thunk, nullptr);
+       avctx->pb = avio_alloc_context(buf, MUX_BUFFER_SIZE, 1, this, nullptr, nullptr, nullptr);
+       avctx->pb->write_data_type = &VideoEncoder::write_packet2_thunk;
+       avctx->pb->ignore_boundary_point = 1;
 
        Mux::Codec video_codec;
        if (global_flags.uncompressed_video_to_http) {
@@ -136,26 +146,23 @@ void VideoEncoder::open_output_stream()
        }
 
        int time_base = global_flags.stream_coarse_timebase ? COARSE_TIMEBASE : TIMEBASE;
-       stream_mux_writing_header = true;
-       stream_mux.reset(new Mux(avctx, width, height, video_codec, video_extradata, stream_audio_encoder->get_ctx(), time_base, this));
-       stream_mux_writing_header = false;
-       httpd->set_header(stream_mux_header);
-       stream_mux_header.clear();
+       stream_mux.reset(new Mux(avctx, width, height, video_codec, video_extradata, stream_audio_encoder->get_codec_parameters().get(), time_base,
+               /*write_callback=*/nullptr));
 }
 
-int VideoEncoder::write_packet_thunk(void *opaque, uint8_t *buf, int buf_size)
+int VideoEncoder::write_packet2_thunk(void *opaque, uint8_t *buf, int buf_size, AVIODataMarkerType type, int64_t time)
 {
        VideoEncoder *video_encoder = (VideoEncoder *)opaque;
-       return video_encoder->write_packet(buf, buf_size);
+       return video_encoder->write_packet2(buf, buf_size, type, time);
 }
 
-int VideoEncoder::write_packet(uint8_t *buf, int buf_size)
+int VideoEncoder::write_packet2(uint8_t *buf, int buf_size, AVIODataMarkerType type, int64_t time)
 {
-       if (stream_mux_writing_header) {
+       if (type == AVIO_DATA_MARKER_HEADER) {
                stream_mux_header.append((char *)buf, buf_size);
+               httpd->set_header(stream_mux_header);
        } else {
-               httpd->add_data((char *)buf, buf_size, stream_mux_writing_keyframes);
-               stream_mux_writing_keyframes = false;
+               httpd->add_data((char *)buf, buf_size, type == AVIO_DATA_MARKER_SYNC_POINT);
        }
        return buf_size;
 }