X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=h264encode.cpp;h=dd2c80560840c52155dca439c1a8c1335145731f;hb=eb15ac766b68cbb5fb563d6e1c73e4a58b2b80fb;hp=5fa01bd48d29ab4a2286ed88117544989961a9ef;hpb=7a6878b637f9b323a83411d155437752cd83eff0;p=nageru diff --git a/h264encode.cpp b/h264encode.cpp index 5fa01bd..dd2c805 100644 --- a/h264encode.cpp +++ b/h264encode.cpp @@ -7,11 +7,11 @@ #include #include #include -#include -#include +#include +#include #include +#include #include -#include #include #include #include @@ -20,12 +20,17 @@ #include #include #include +#include +#include #include #include #include #include +#include #include "context.h" +#include "defs.h" +#include "httpd.h" #include "timebase.h" class QOpenGLContext; @@ -109,7 +114,7 @@ static int frame_width = 176; static int frame_height = 144; static int frame_width_mbaligned; static int frame_height_mbaligned; -static int frame_rate = 60; +static int frame_rate = FPS; static unsigned int frame_bitrate = 0; static unsigned int frame_slices = 1; static double frame_size = 0; @@ -117,7 +122,7 @@ static int initial_qp = 15; //static int initial_qp = 28; static int minimal_qp = 0; static int intra_period = 30; -static int intra_idr_period = 60; +static int intra_idr_period = FPS; static int ip_period = 3; static int rc_mode = -1; static int rc_default_modes[] = { @@ -339,7 +344,17 @@ static void sps_rbsp(bitstream *bs) bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */ bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */ bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */ - bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */ + bitstream_put_ui(bs, 1, 1); /* video_signal_type_present_flag */ + { + bitstream_put_ui(bs, 5, 3); /* video_format (5 = Unspecified) */ + bitstream_put_ui(bs, 0, 1); /* video_full_range_flag */ + bitstream_put_ui(bs, 1, 1); /* colour_description_present_flag */ + { + bitstream_put_ui(bs, 1, 8); /* colour_primaries (1 = BT.709) */ + bitstream_put_ui(bs, 2, 8); /* transfer_characteristics (2 = unspecified, since we use sRGB) */ + bitstream_put_ui(bs, 6, 8); /* matrix_coefficients (6 = BT.601/SMPTE 170M) */ + } + } bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */ bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */ { @@ -1655,8 +1670,6 @@ int H264Encoder::save_codeddata(storage_task task) AVPacket pkt; memset(&pkt, 0, sizeof(pkt)); pkt.buf = nullptr; - pkt.pts = av_rescale_q(task.pts + global_delay, AVRational{1, TIMEBASE}, avstream_video->time_base); - pkt.dts = av_rescale_q(task.dts + global_delay, AVRational{1, TIMEBASE}, avstream_video->time_base); pkt.data = reinterpret_cast(&data[0]); pkt.size = data.size(); pkt.stream_index = 0; @@ -1666,7 +1679,7 @@ int H264Encoder::save_codeddata(storage_task task) pkt.flags = 0; } //pkt.duration = 1; - av_interleaved_write_frame(avctx, &pkt); + httpd->add_packet(pkt, task.pts + global_delay, task.dts + global_delay); } // Encode and add all audio frames up to and including the pts of this video frame. // (They can never be queued to us after the video frame they belong to, only before.) @@ -1682,6 +1695,7 @@ int H264Encoder::save_codeddata(storage_task task) audio = move(it->second); pending_audio_frames.erase(it); } + AVFrame *frame = avcodec_alloc_frame(); frame->nb_samples = audio.size() / 2; frame->format = AV_SAMPLE_FMT_FLT; @@ -1699,12 +1713,10 @@ int H264Encoder::save_codeddata(storage_task task) pkt.data = nullptr; pkt.size = 0; int got_output; - avcodec_encode_audio2(avstream_audio->codec, &pkt, frame, &got_output); + avcodec_encode_audio2(context_audio, &pkt, frame, &got_output); if (got_output) { - pkt.pts = av_rescale_q(audio_pts + global_delay, AVRational{1, TIMEBASE}, avstream_audio->time_base); - pkt.dts = pkt.pts; pkt.stream_index = 1; - av_interleaved_write_frame(avctx, &pkt); + httpd->add_packet(pkt, audio_pts + global_delay, audio_pts + global_delay); } // TODO: Delayed frames. avcodec_free_frame(&frame); @@ -1818,57 +1830,22 @@ static int print_input() return 0; } - -//H264Encoder::H264Encoder(SDL_Window *window, SDL_GLContext context, int width, int height, const char *output_filename) -H264Encoder::H264Encoder(QSurface *surface, int width, int height, const char *output_filename) - : current_storage_frame(0), surface(surface) - //: width(width), height(height), current_encoding_frame(0) +H264Encoder::H264Encoder(QSurface *surface, int width, int height, HTTPD *httpd) + : current_storage_frame(0), surface(surface), httpd(httpd) { - av_register_all(); - avctx = avformat_alloc_context(); - avctx->oformat = av_guess_format(NULL, output_filename, NULL); - strcpy(avctx->filename, output_filename); - if (avio_open2(&avctx->pb, output_filename, AVIO_FLAG_WRITE, &avctx->interrupt_callback, NULL) < 0) { - fprintf(stderr, "%s: avio_open2() failed\n", output_filename); - exit(1); - } - AVCodec *codec_video = avcodec_find_encoder(AV_CODEC_ID_H264); - avstream_video = avformat_new_stream(avctx, codec_video); - if (avstream_video == nullptr) { - fprintf(stderr, "%s: avformat_new_stream() failed\n", output_filename); - exit(1); - } - avstream_video->time_base = AVRational{1, TIMEBASE}; - avstream_video->codec->width = width; - avstream_video->codec->height = height; - avstream_video->codec->time_base = AVRational{1, TIMEBASE}; - avstream_video->codec->ticks_per_frame = 1; // or 2? - AVCodec *codec_audio = avcodec_find_encoder(AV_CODEC_ID_MP3); - avstream_audio = avformat_new_stream(avctx, codec_audio); - if (avstream_audio == nullptr) { - fprintf(stderr, "%s: avformat_new_stream() failed\n", output_filename); - exit(1); - } - avstream_audio->time_base = AVRational{1, TIMEBASE}; - avstream_audio->codec->bit_rate = 256000; - avstream_audio->codec->sample_rate = 48000; - avstream_audio->codec->sample_fmt = AV_SAMPLE_FMT_FLTP; - avstream_audio->codec->channels = 2; - avstream_audio->codec->channel_layout = AV_CH_LAYOUT_STEREO; - avstream_audio->codec->time_base = AVRational{1, TIMEBASE}; - - /* open it */ - if (avcodec_open2(avstream_audio->codec, codec_audio, NULL) < 0) { + context_audio = avcodec_alloc_context3(codec_audio); + context_audio->bit_rate = 256000; + context_audio->sample_rate = OUTPUT_FREQUENCY; + context_audio->sample_fmt = AV_SAMPLE_FMT_FLTP; + context_audio->channels = 2; + context_audio->channel_layout = AV_CH_LAYOUT_STEREO; + context_audio->time_base = AVRational{1, TIMEBASE}; + if (avcodec_open2(context_audio, codec_audio, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } - if (avformat_write_header(avctx, NULL) < 0) { - fprintf(stderr, "%s: avformat_write_header() failed\n", output_filename); - exit(1); - } - frame_width = width; frame_height = height; frame_width_mbaligned = (frame_width + 15) & (~15); @@ -1892,7 +1869,7 @@ H264Encoder::H264Encoder(QSurface *surface, int width, int height, const char *o copy_thread = std::thread([this]{ //SDL_GL_MakeCurrent(window, context); - QOpenGLContext *context = create_context(); + QOpenGLContext *context = create_context(this->surface); eglBindAPI(EGL_OPENGL_API); if (!make_current(context, this->surface)) { printf("display=%p surface=%p context=%p curr=%p err=%d\n", eglGetCurrentDisplay(), this->surface, context, eglGetCurrentContext(), @@ -1920,9 +1897,6 @@ H264Encoder::~H264Encoder() release_encode(); deinit_va(); - - av_write_trailer(avctx); - avformat_free_context(avctx); } bool H264Encoder::begin_frame(GLuint *y_tex, GLuint *cbcr_tex)