Save Media frame info to the Media object

This commit is contained in:
Aaro Altonen 2020-09-16 11:31:35 +03:00
parent 7559482a84
commit 2d1c6bd79c
2 changed files with 50 additions and 34 deletions

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <unordered_map>
#include <unordered_set>
#include "../rtp.hh" #include "../rtp.hh"
#include "../socket.hh" #include "../socket.hh"
@ -11,6 +13,19 @@ namespace uvg_rtp {
namespace formats { namespace formats {
typedef struct media_info {
uint32_t s_seq;
uint32_t e_seq;
size_t npkts;
size_t size;
std::map<uint16_t, uvg_rtp::frame::rtp_frame *> fragments;
} media_info_t;
typedef struct media_frame_info {
std::unordered_map<uint32_t, media_info> frames;
std::unordered_set<uint32_t> dropped;
} media_frame_info_t;
class media { class media {
public: public:
media(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp_ctx, int flags); media(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp_ctx, int flags);
@ -36,6 +51,9 @@ namespace uvg_rtp {
* Return RTP_GENERIC_ERROR if the packet was corrupted in some way */ * Return RTP_GENERIC_ERROR if the packet was corrupted in some way */
static rtp_error_t packet_handler(void *arg, int flags, frame::rtp_frame **frame); static rtp_error_t packet_handler(void *arg, int flags, frame::rtp_frame **frame);
/* Return pointer to the internal frame info structure which is relayed to packet handler */
media_frame_info_t *get_hevc_frame_info();
protected: protected:
virtual rtp_error_t __push_frame(uint8_t *data, size_t data_len, int flags); virtual rtp_error_t __push_frame(uint8_t *data, size_t data_len, int flags);
@ -43,6 +61,9 @@ namespace uvg_rtp {
uvg_rtp::rtp *rtp_ctx_; uvg_rtp::rtp *rtp_ctx_;
int flags_; int flags_;
uvg_rtp::frame_queue *fqueue_; uvg_rtp::frame_queue *fqueue_;
private:
media_frame_info_t minfo_;
}; };
}; };
}; };

View File

@ -11,7 +11,7 @@
#define INVALID_SEQ 0xffffffff #define INVALID_SEQ 0xffffffff
uvg_rtp::formats::media::media(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp_ctx, int flags): uvg_rtp::formats::media::media(uvg_rtp::socket *socket, uvg_rtp::rtp *rtp_ctx, int flags):
socket_(socket), rtp_ctx_(rtp_ctx), flags_(flags) socket_(socket), rtp_ctx_(rtp_ctx), flags_(flags), minfo_{}
{ {
fqueue_ = new uvg_rtp::frame_queue(socket, rtp_ctx, flags); fqueue_ = new uvg_rtp::frame_queue(socket, rtp_ctx, flags);
} }
@ -122,51 +122,46 @@ rtp_error_t uvg_rtp::formats::media::__push_frame(uint8_t *data, size_t data_len
#endif #endif
} }
uvg_rtp::formats::media_frame_info_t *uvg_rtp::formats::media::get_hevc_frame_info()
{
return &minfo_;
}
rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rtp::frame::rtp_frame **out) rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rtp::frame::rtp_frame **out)
{ {
(void)arg; auto minfo = (uvg_rtp::formats::media_frame_info_t *)arg;
auto frame = *out;
struct frame_info { uint32_t ts = frame->header.timestamp;
uint32_t s_seq; uint32_t seq = frame->header.seq;
uint32_t e_seq; size_t recv = 0;
size_t npkts;
size_t size;
std::map<uint16_t, uvg_rtp::frame::rtp_frame *> fragments;
};
static std::unordered_map<uint32_t, frame_info> frames;
auto frame = *out;
uint32_t ts = frame->header.timestamp;
uint32_t seq = frame->header.seq;
size_t recv = 0;
/* If fragmentation of generic frame has not been enabled, we can just return the frame /* If fragmentation of generic frame has not been enabled, we can just return the frame
* in "out" because RTP packet handler has done all the necessasry stuff for small RTP packets */ * in "out" because RTP packet handler has done all the necessasry stuff for small RTP packets */
if (!(flags & RCE_FRAGMENT_GENERIC)) if (!(flags & RCE_FRAGMENT_GENERIC))
return RTP_PKT_READY; return RTP_PKT_READY;
if (frames.find(ts) != frames.end()) { if (minfo->frames.find(ts) != minfo->frames.end()) {
frames[ts].npkts++; minfo->frames[ts].npkts++;
frames[ts].fragments[seq] = frame; minfo->frames[ts].fragments[seq] = frame;
frames[ts].size += frame->payload_len; minfo->frames[ts].size += frame->payload_len;
*out = nullptr; *out = nullptr;
if (frame->header.marker) if (frame->header.marker)
frames[ts].e_seq = seq; minfo->frames[ts].e_seq = seq;
if (frames[ts].e_seq != INVALID_SEQ && frames[ts].s_seq != INVALID_SEQ) { if (minfo->frames[ts].e_seq != INVALID_SEQ && minfo->frames[ts].s_seq != INVALID_SEQ) {
if (frames[ts].s_seq > frames[ts].e_seq) if (minfo->frames[ts].s_seq > minfo->frames[ts].e_seq)
recv = 0xffff - frames[ts].s_seq + frames[ts].e_seq + 2; recv = 0xffff - minfo->frames[ts].s_seq + minfo->frames[ts].e_seq + 2;
else else
recv = frames[ts].e_seq - frames[ts].s_seq + 1; recv = minfo->frames[ts].e_seq - minfo->frames[ts].s_seq + 1;
if (recv == frames[ts].npkts) { if (recv == minfo->frames[ts].npkts) {
auto retframe = uvg_rtp::frame::alloc_rtp_frame(frames[ts].size); auto retframe = uvg_rtp::frame::alloc_rtp_frame(minfo->frames[ts].size);
size_t ptr = 0; size_t ptr = 0;
std::memcpy(&retframe->header, &frame->header, sizeof(frame->header)); std::memcpy(&retframe->header, &frame->header, sizeof(frame->header));
for (auto& frag : frames[ts].fragments) { for (auto& frag : minfo->frames[ts].fragments) {
std::memcpy( std::memcpy(
retframe->payload + ptr, retframe->payload + ptr,
frag.second->payload, frag.second->payload,
@ -176,7 +171,7 @@ rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rt
(void)uvg_rtp::frame::dealloc_frame(frag.second); (void)uvg_rtp::frame::dealloc_frame(frag.second);
} }
frames.erase(ts); minfo->frames.erase(ts);
(void)uvg_rtp::frame::dealloc_frame(*out); (void)uvg_rtp::frame::dealloc_frame(*out);
*out = retframe; *out = retframe;
return RTP_PKT_READY; return RTP_PKT_READY;
@ -184,11 +179,11 @@ rtp_error_t uvg_rtp::formats::media::packet_handler(void *arg, int flags, uvg_rt
} }
} else { } else {
if (frame->header.marker) { if (frame->header.marker) {
frames[ts].npkts = 1; minfo->frames[ts].npkts = 1;
frames[ts].s_seq = seq; minfo->frames[ts].s_seq = seq;
frames[ts].e_seq = INVALID_SEQ; minfo->frames[ts].e_seq = INVALID_SEQ;
frames[ts].fragments[seq] = frame; minfo->frames[ts].fragments[seq] = frame;
frames[ts].size = frame->payload_len; minfo->frames[ts].size = frame->payload_len;
*out = nullptr; *out = nullptr;
} else { } else {
return RTP_PKT_READY; return RTP_PKT_READY;