X-Git-Url: https://git.sesse.net/?p=nageru;a=blobdiff_plain;f=httpd.cpp;h=f6441768bbdde1df3d31e2b42a2cb13430019376;hp=f82c8038e55f61b90031534dd88c540e17d53d7e;hb=refs%2Fheads%2Fffmpeg-audio-only;hpb=55f8957b5c6aa0a5baaf3cb631e6219182b97026 diff --git a/httpd.cpp b/httpd.cpp index f82c803..f644176 100644 --- a/httpd.cpp +++ b/httpd.cpp @@ -10,6 +10,9 @@ #include #include #include +extern "C" { +#include +} #include "defs.h" #include "metacube2.h" @@ -27,13 +30,7 @@ HTTPD::HTTPD() HTTPD::~HTTPD() { - if (mhd) { - MHD_quiesce_daemon(mhd); - for (Stream *stream : streams) { - stream->stop(); - } - MHD_stop_daemon(mhd); - } + stop(); } void HTTPD::start(int port) @@ -49,11 +46,23 @@ void HTTPD::start(int port) } } -void HTTPD::add_data(const char *buf, size_t size, bool keyframe) +void HTTPD::stop() +{ + if (mhd) { + MHD_quiesce_daemon(mhd); + for (Stream *stream : streams) { + stream->stop(); + } + MHD_stop_daemon(mhd); + mhd = nullptr; + } +} + +void HTTPD::add_data(const char *buf, size_t size, bool keyframe, int64_t time, AVRational timebase) { unique_lock lock(streams_mutex); for (Stream *stream : streams) { - stream->add_data(buf, size, keyframe ? Stream::DATA_TYPE_KEYFRAME : Stream::DATA_TYPE_OTHER); + stream->add_data(buf, size, keyframe ? Stream::DATA_TYPE_KEYFRAME : Stream::DATA_TYPE_OTHER, time, timebase); } } @@ -113,7 +122,7 @@ int HTTPD::answer_to_connection(MHD_Connection *connection, } HTTPD::Stream *stream = new HTTPD::Stream(this, framing); - stream->add_data(header.data(), header.size(), Stream::DATA_TYPE_HEADER); + stream->add_data(header.data(), header.size(), Stream::DATA_TYPE_HEADER, AV_NOPTS_VALUE, AVRational{ 1, 0 }); { unique_lock lock(streams_mutex); streams.insert(stream); @@ -187,7 +196,7 @@ ssize_t HTTPD::Stream::reader_callback(uint64_t pos, char *buf, size_t max) return ret; } -void HTTPD::Stream::add_data(const char *buf, size_t buf_size, HTTPD::Stream::DataType data_type) +void HTTPD::Stream::add_data(const char *buf, size_t buf_size, HTTPD::Stream::DataType data_type, int64_t time, AVRational timebase) { if (buf_size == 0) { return; @@ -202,15 +211,34 @@ void HTTPD::Stream::add_data(const char *buf, size_t buf_size, HTTPD::Stream::Da unique_lock lock(buffer_mutex); if (framing == FRAMING_METACUBE) { - metacube2_block_header hdr; - memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync)); - hdr.size = htonl(buf_size); int flags = 0; if (data_type == DATA_TYPE_HEADER) { flags |= METACUBE_FLAGS_HEADER; } else if (data_type == DATA_TYPE_OTHER) { flags |= METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START; } + + // If we're about to send a keyframe, send a pts metadata block + // to mark its time. + if ((flags & METACUBE_FLAGS_NOT_SUITABLE_FOR_STREAM_START) == 0 && time != AV_NOPTS_VALUE) { + metacube2_pts_packet packet; + packet.type = htobe64(METACUBE_METADATA_TYPE_NEXT_BLOCK_PTS); + packet.pts = htobe64(time); + packet.timebase_num = htobe64(timebase.num); + packet.timebase_den = htobe64(timebase.den); + + metacube2_block_header hdr; + memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync)); + hdr.size = htonl(sizeof(packet)); + hdr.flags = htons(METACUBE_FLAGS_METADATA); + hdr.csum = htons(metacube2_compute_crc(&hdr)); + buffered_data.emplace_back((char *)&hdr, sizeof(hdr)); + buffered_data.emplace_back((char *)&packet, sizeof(packet)); + } + + metacube2_block_header hdr; + memcpy(hdr.sync, METACUBE2_SYNC, sizeof(hdr.sync)); + hdr.size = htonl(buf_size); hdr.flags = htons(flags); hdr.csum = htons(metacube2_compute_crc(&hdr)); buffered_data.emplace_back((char *)&hdr, sizeof(hdr));