UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
Video Decoder

Files

file  video_decoders.cpp
 
file  video_decoders.h
 Video RTP decoder.
 

Functions

int decode_video_frame (struct coded_data *received_data, void *decoder_data, struct pbuf_stats *stats)
 Decodes a participant buffer representing one video frame.
 
bool parse_video_hdr (const uint32_t *hdr, struct video_desc *desc)
 
void video_decoder_destroy (struct state_video_decoder *decoder)
 Destroys decoder created with decoder_init()
 
struct state_video_decoder * video_decoder_init (struct module *parent, enum video_mode, struct display *display, const char *encryption)
 
bool video_decoder_register_display (struct state_video_decoder *decoder, struct display *display)
 Registers video display to be used for displaying decoded video frames.
 
void video_decoder_remove_display (struct state_video_decoder *decoder)
 This removes display from current decoder.
 

Detailed Description

Function Documentation

◆ decode_video_frame()

int decode_video_frame ( struct coded_data * cdata,
void * decoder_data,
struct pbuf_stats * stats )

Decodes a participant buffer representing one video frame.

Parameters
cdataPBUF buffer
decoder_datavcodec_state containing decoder state and some additional data
Return values
trueif decoding was successful. It stil doesn't mean that the frame will be correctly displayed, decoding may fail in some subsequent (asynchronous) steps.
falseif decoding failed

Zero missing parts of framebuffer - this may be useful for compressed video (which may be also with FEC - but we use systematic codes therefore it may benefit from that as well).

Definition at line 1502 of file video_decoders.cpp.

1503{
1504 struct vcodec_state *pbuf_data = (struct vcodec_state *) decoder_data;
1505 struct state_video_decoder *decoder = pbuf_data->decoder;
1506
1507 bool ret = true;
1508 int prints=0;
1509 int max_substreams = decoder->max_substreams;
1510
1511 vector<uint32_t> buffer_num(max_substreams);
1512 // the following is just FEC related optimalization - normally we fill up
1513 // allocated buffers when we have compressed data. But in case of FEC, there
1514 // is just the FEC buffer present, so we point to it instead to copying
1515 struct video_frame *frame = vf_alloc(max_substreams);
1517 unique_ptr<map<int, int>[]> pckt_list(new map<int, int>[max_substreams]);
1518
1519 int buffer_number = 0;
1520 bool buffer_swapped = false;
1521
1522 // We have no framebuffer assigned, exitting
1523 if(!decoder->display) {
1524 vf_free(frame);
1525 return false;
1526 }
1527
1528 main_msg_reconfigure *msg_reconf;
1529 while ((msg_reconf = decoder->msg_queue.pop(true /* nonblock */))) {
1530 if (msg_reconf->force) {
1531 reconfigure_helper(decoder, msg_reconf->desc,
1532 msg_reconf->compress_internal_prop);
1533 log_msg(LOG_LEVEL_VERBOSE, "forced reconf\n");
1534 } else {
1536 decoder, msg_reconf->desc,
1537 msg_reconf->compress_internal_prop);
1538 }
1539 if (msg_reconf->last_frame) {
1540 decoder->fec_queue.push(std::move(msg_reconf->last_frame));
1541 }
1542 delete msg_reconf;
1543 }
1544
1545 frame->ssrc = cdata->data->ssrc;
1546 frame->timestamp = cdata->data->ts;
1547 int pt = cdata->data->pt;
1548 if (PT_VIDEO_HAS_FEC(pt)) {
1549 const uint32_t *hdr = (uint32_t *)(void *)cdata->data->data;
1550 const uint32_t tmp = ntohl(hdr[3]);
1551 const int k = tmp >> 19;
1552 const int m = 0x1fff & (tmp >> 6);
1553 const int c = 0x3f & tmp;
1554 const int seed = ntohl(hdr[4]);
1555 frame->fec_params =
1556 fec_desc(fec::fec_type_from_pt(pt), k, m, c, seed);
1557 }
1558
1559 while (cdata != NULL) {
1560 int len;
1561 const char *data;
1562 rtp_packet *pckt = cdata->data;
1563 enum openssl_mode crypto_mode = MODE_AES128_NONE;
1564
1565 pt = pckt->pt;
1566 const uint32_t *hdr = (uint32_t *)(void *) pckt->data;
1567 const uint32_t data_pos = ntohl(hdr[1]);
1568 uint32_t tmp = ntohl(hdr[0]);
1569 const uint32_t substream = tmp >> 22;
1570 buffer_number = tmp & 0x3fffff;
1571 const int buffer_length = ntohl(hdr[2]);
1572
1573 if (PT_VIDEO_IS_ENCRYPTED(pt)) {
1574 if(!decoder->decrypt) {
1577 }
1578 } else {
1579 if(decoder->decrypt) {
1582 }
1583 }
1584
1585 switch (pt) {
1586 case PT_VIDEO:
1587 len = pckt->data_len - sizeof(video_payload_hdr_t);
1588 data = (const char *) hdr + sizeof(video_payload_hdr_t);
1589 break;
1590 case PT_VIDEO_RS:
1591 case PT_VIDEO_LDGM:
1592 len = pckt->data_len - sizeof(fec_payload_hdr_t);
1593 data = (const char *) hdr + sizeof(fec_payload_hdr_t);
1594 break;
1595 case PT_ENCRYPT_VIDEO:
1598 {
1599 size_t media_hdr_len = pt == PT_ENCRYPT_VIDEO ? sizeof(video_payload_hdr_t) : sizeof(fec_payload_hdr_t);
1600 len = pckt->data_len - sizeof(crypto_payload_hdr_t) - media_hdr_len;
1601 data = (const char *)hdr + sizeof(crypto_payload_hdr_t) + media_hdr_len;
1602 uint32_t crypto_hdr = ntohl(*(const uint32_t *)(const void *)((const char *)hdr + media_hdr_len));
1603 crypto_mode = (enum openssl_mode) (crypto_hdr >> 24);
1604 if (crypto_mode == MODE_AES128_NONE || crypto_mode > MODE_AES128_MAX) {
1605 log_msg(LOG_LEVEL_WARNING, "Unknown cipher mode: %d\n", (int) crypto_mode);
1606 ret = false;
1607 goto cleanup;
1608 }
1609 }
1610 break;
1611 default:
1612 if (pt == PT_Unassign_Type95) {
1613 log_msg_once(LOG_LEVEL_WARNING, to_fourcc('U', 'V', 'P', 'T'), MOD_NAME "Unassigned PT 95 received, ignoring.\n");
1614 } else {
1615 LOG(LOG_LEVEL_WARNING) << MOD_NAME "Unknown packet type: " << pckt->pt << ".\n";
1616 }
1617 ret = false;
1618 goto cleanup;
1619 }
1620
1621 if ((int) substream >= max_substreams) {
1622 log_msg(LOG_LEVEL_WARNING, "[decoder] received substream ID %d. Expecting at most %d substreams. Did you set -M option?\n",
1623 substream, max_substreams);
1624 // the guess is valid - we start with highest substream number (anytime - since it holds a m-bit)
1625 // in next iterations, index is valid
1626 enum video_mode video_mode =
1627 guess_video_mode(substream + 1);
1628 if (video_mode != VIDEO_UNKNOWN) {
1629 log_msg(LOG_LEVEL_NOTICE, "[decoder] Guessing mode: ");
1631 decoder->received_vid_desc.width = 0; // just for sure, that we reconfigure in next iteration
1632 log_msg(LOG_LEVEL_NOTICE, "%s. Check if it is correct.\n", get_video_mode_description(decoder->video_mode));
1633 } else {
1634 log_msg(LOG_LEVEL_FATAL, "[decoder] Unknown video mode!\n");
1635 handle_error(1);
1636 }
1637 // we need skip this frame (variables are illegal in this iteration
1638 // and in case that we got unrecognized number of substreams - exit
1639 ret = false;
1640 goto cleanup;
1641 }
1642
1643 char plaintext[RTP_MAX_PACKET_LEN]; // will be actually shorter
1644 if (PT_VIDEO_IS_ENCRYPTED(pt)) {
1645 int data_len;
1646
1647 if((data_len = decoder->dec_funcs->decrypt(decoder->decrypt,
1648 data, len,
1649 (const char *) hdr, pt == PT_ENCRYPT_VIDEO ?
1650 sizeof(video_payload_hdr_t) : sizeof(fec_payload_hdr_t),
1651 plaintext, crypto_mode)) == 0) {
1652 goto next_packet;
1653 }
1654 data = (char *) plaintext;
1655 len = data_len;
1656 }
1657
1658 if (!PT_VIDEO_HAS_FEC(pt))
1659 {
1660 /* Critical section
1661 * each thread *MUST* wait here if this condition is true
1662 */
1663 check_for_mode_change(decoder, hdr);
1664
1665 // hereafter, display framebuffer can be used, so we
1666 // check if we got it
1667 if (FRAMEBUFFER_NOT_READY(decoder)) {
1668 vf_free(frame);
1669 return false;
1670 }
1671 }
1672
1673 buffer_num[substream] = buffer_number;
1674 frame->tiles[substream].data_len = buffer_length;
1675 pckt_list[substream][data_pos] = len;
1676
1677 if ((pt == PT_VIDEO || pt == PT_ENCRYPT_VIDEO) && decoder->decoder_type == LINE_DECODER) {
1678 struct tile *tile = NULL;
1679 if(!buffer_swapped) {
1681 buffer_swapped = true;
1682 unique_lock<mutex> lk(decoder->lock);
1683 decoder->buffer_swapped = false;
1684 }
1685
1686 if (!decoder->merged_fb) {
1687 tile = vf_get_tile(decoder->frame, substream);
1688 } else {
1689 tile = vf_get_tile(decoder->frame, 0);
1690 }
1691
1692 struct line_decoder *line_decoder =
1693 &decoder->line_decoder[substream];
1694
1695 /* End of critical section */
1696
1697 /* MAGIC, don't touch it, you definitely break it
1698 * *source* is data from network, *destination* is frame buffer
1699 */
1700
1701 /* compute Y pos in source frame and convert it to
1702 * byte offset in the destination frame
1703 */
1704 int y = (data_pos / line_decoder->src_linesize) * line_decoder->dst_pitch;
1705
1706 /* compute X pos in source frame */
1707 int s_x = data_pos % line_decoder->src_linesize;
1708
1709 /* convert X pos from source frame into the destination frame.
1710 * it is byte offset from the beginning of a line.
1711 */
1712 int d_x = s_x * line_decoder->conv_num / line_decoder->conv_den;
1713
1714 /* pointer to data payload in packet */
1715 auto *source = (const unsigned char *)(data);
1716
1717 /* copy whole packet that can span several lines.
1718 * we need to clip data (v210 case) or center data (RGBA, R10k cases)
1719 */
1720 while (len > 0) {
1721 /* len id payload length in source BPP
1722 * decoder needs len in destination BPP, so convert it
1723 */
1724 int l = len * line_decoder->conv_num / line_decoder->conv_den;
1725
1726 /* do not copy multiple lines, we need to
1727 * copy (& clip, center) line by line
1728 */
1729 if (l + d_x > (int) line_decoder->dst_linesize) {
1730 l = line_decoder->dst_linesize - d_x;
1731 }
1732
1733 /* compute byte offset in destination frame */
1734 const uint32_t offset = y + d_x;
1735
1736 /* watch the SEGV */
1737 if (l + line_decoder->base_offset + offset <= tile->data_len) {
1738 /*decode frame:
1739 * we have offset for destination
1740 * we update source contiguously
1741 * we pass {r,g,b}shifts */
1742 line_decoder->decode_line((unsigned char*)tile->data + line_decoder->base_offset + offset, source, l,
1743 line_decoder->shifts[0], line_decoder->shifts[1],
1744 line_decoder->shifts[2]);
1745 /* we decoded one line (or a part of one line) to the end of the line
1746 * so decrease *source* len by 1 line (or that part of the line */
1747 len -= line_decoder->src_linesize - s_x;
1748 /* jump in source by the same amount */
1749 source += line_decoder->src_linesize - s_x;
1750 } else {
1751 /* this should not ever happen as we call reconfigure before each packet
1752 * iff reconfigure is needed. But if it still happens, something is terribly wrong
1753 * say it loudly
1754 */
1755 if((prints % 100) == 0) {
1756 log_msg(LOG_LEVEL_ERROR, "WARNING!! Discarding input data as frame buffer is too small.\n"
1757 "Well this should not happened. Expect troubles pretty soon.\n");
1758 }
1759 prints++;
1760 len = 0;
1761 }
1762 /* each new line continues from the beginning */
1763 d_x = 0; /* next line from beginning */
1764 s_x = 0;
1765 y += line_decoder->dst_pitch; /* next line */
1766 }
1767 } else { /* PT_VIDEO_LDGM or external decoder */
1768 if(!frame->tiles[substream].data) {
1769 frame->tiles[substream].data = (char *) malloc(buffer_length + PADDING);
1770 }
1771
1772 if (data_pos + len > (unsigned) buffer_length) {
1773 if((prints % 100) == 0) {
1774 log_msg(LOG_LEVEL_ERROR, "WARNING!! Discarding input data as frame buffer is too small.\n"
1775 "Well this should not happened. Expect troubles pretty soon.\n");
1776 }
1777 prints++;
1778 len = max<int>(0, buffer_length - data_pos);
1779 }
1780 memcpy(frame->tiles[substream].data + data_pos,
1781 (const unsigned char *)data, len);
1782 }
1783
1784next_packet:
1785 cdata = cdata->nxt;
1786 }
1787
1788 if (FRAMEBUFFER_NOT_READY(decoder) && (pt == PT_VIDEO || pt == PT_ENCRYPT_VIDEO)) {
1789 ret = false;
1790 goto cleanup;
1791 }
1792
1793 assert(ret);
1794
1798 if (decoder->decoder_type != LINE_DECODER) {
1799 for(int i = 0; i < max_substreams; ++i) {
1800 unsigned int last_end = 0;
1801 for (auto const & packets : pckt_list[i]) {
1802 unsigned int start = packets.first;
1803 unsigned int len = packets.second;
1804 if (last_end < start) {
1805 memset(frame->tiles[i].data + last_end, 0, start - last_end);
1806 }
1807 last_end = start + len;
1808 }
1809 if (last_end < frame->tiles[i].data_len) {
1810 memset(frame->tiles[i].data + last_end, 0, frame->tiles[i].data_len - last_end);
1811 }
1812 }
1813 }
1814
1815 {
1816 unsigned int frame_size = 0;
1817 for (int i = 0; i < max_substreams; ++i) {
1818 frame_size += frame->tiles[i].data_len;
1819 }
1820 pbuf_data->max_frame_size =
1821 max(pbuf_data->max_frame_size, frame_size);
1822 // format message
1823 unique_ptr <frame_msg> fec_msg (new frame_msg(decoder->control, decoder->stats));
1824 fec_msg->buffer_num = std::move(buffer_num);
1825 fec_msg->recv_frame = frame;
1826 frame = NULL;
1827 fec_msg->pckt_list = std::move(pckt_list);
1828 fec_msg->received_pkts_cum = stats->received_pkts_cum;
1829 fec_msg->expected_pkts_cum = stats->expected_pkts_cum;
1830
1831 auto t0 = std::chrono::high_resolution_clock::now();
1832 decoder->fec_queue.push(std::move(fec_msg));
1833 auto t1 = std::chrono::high_resolution_clock::now();
1834 double tpf = 1.0 / decoder->display_desc.fps;
1835 if (std::chrono::duration_cast<std::chrono::duration<double>>(t1 - t0).count() > tpf && decoder->stats.displayed > 20) {
1836 decoder->slow_msg.print("Your computer may be too SLOW to play this !!!\n");
1837 }
1838
1839 }
1840cleanup:
1841 ;
1842 if (ret) {
1843 vf_free(frame);
1844 }
1845 pbuf_data->decoded++;
1846
1847 decoder->stats.update(buffer_number);
1848
1849 return ret;
1850}
struct video_frame * frame
int void size_t * len
struct video_frame * vf_alloc(int count)
Allocates blank video frame.
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void vf_data_deleter(struct video_frame *buf)
T pop(bool nonblocking=false)
void push(T const &message)
static __device__ const float offset
Definition cuda_dxt.cu:139
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
void log_msg_once(int level, uint32_t id, const char *msg,...)
Definition debug.cpp:137
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
void handle_error(int status)
Definition host.cpp:1184
#define to_fourcc(a, b, c, d)
Creates FourCC word.
Definition macros.h:114
openssl_mode
only GCM provides autenticity, other modes only check integrity (CRC)
@ MODE_AES128_NONE
@ MODE_AES128_MAX
rtp_packet
Definition rtp.h:126
#define RTP_MAX_PACKET_LEN
Definition rtp.h:61
#define PT_ENCRYPT_VIDEO
Definition rtp_types.h:69
#define PT_ENCRYPT_VIDEO_RS
Definition rtp_types.h:74
#define PT_VIDEO
Definition rtp_types.h:66
uint32_t fec_payload_hdr_t[5]
Definition rtp_types.h:152
#define PT_VIDEO_IS_ENCRYPTED(pt)
Definition rtp_types.h:169
#define PT_Unassign_Type95
Definition rtp_types.h:77
#define PT_VIDEO_LDGM
Definition rtp_types.h:68
uint32_t crypto_payload_hdr_t[1]
Definition rtp_types.h:161
#define PT_VIDEO_RS
Definition rtp_types.h:72
#define PT_ENCRYPT_VIDEO_LDGM
Definition rtp_types.h:73
#define PT_VIDEO_HAS_FEC(pt)
Definition rtp_types.h:168
uint32_t video_payload_hdr_t[6]
Definition rtp_types.h:107
static void start()
Definition sdp.c:202
static void cleanup()
Definition sdp.c:195
Definition rtp.c:206
rtp_packet * data
Definition pbuf.h:75
struct coded_data * nxt
Definition pbuf.h:72
static enum fec_type fec_type_from_pt(int pt)
Definition fec.cpp:157
int(* decrypt)(struct openssl_decrypt *decrypt, const char *ciphertext, int ciphertext_len, const char *aad, int aad_len, char *plaintext, enum openssl_mode mode)
long long int received_pkts_cum
Definition pbuf.h:79
long long int expected_pkts_cum
Definition pbuf.h:80
struct line_decoder * line_decoder
is neeeded, use this structure
struct display * display
synchronized_queue< unique_ptr< frame_msg >, 1 > fec_queue
enum decoder_type_t decoder_type
how will the video data be decoded
const struct openssl_decrypt_info * dec_funcs
decrypt state
struct video_frame * frame
struct openssl_decrypt * decrypt
decrypt state
struct video_desc received_vid_desc
description of the network video
bool merged_fb
flag if the display device driver requires tiled video or not
timed_message< LOG_LEVEL_WARNING > slow_msg
shows warning ony in certain interval
unsigned int max_substreams
maximal number of expected substreams
struct control_state * control
struct reported_statistics_cumul stats
stats to be reported through control socket
struct video_desc display_desc
description of the mode that display is currently configured to
enum video_mode video_mode
video mode set for this decoder
synchronized_queue< main_msg_reconfigure *, -1 > msg_queue
Struct tile is an area of video_frame.
Definition types.h:279
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
void print(const char *str)
unsigned int decoded
Definition pbuf.h:95
unsigned int max_frame_size
Definition pbuf.h:93
struct state_video_decoder * decoder
Definition pbuf.h:92
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
void(* data_deleter)(struct video_frame *)
Definition types.h:256
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
uint32_t ssrc
Definition types.h:330
int64_t timestamp
Definition types.h:331
struct video_frame_callbacks callbacks
Definition types.h:324
struct fec_desc fec_params
Definition types.h:328
video_mode
Definition types.h:354
@ VIDEO_UNKNOWN
unspecified video mode
Definition types.h:355
enum video_mode guess_video_mode(int num_substreams)
Tries to guess video mode from number of substreams.
Definition video.cpp:123
const char * get_video_mode_description(enum video_mode video_mode)
Definition video.cpp:118
static void reconfigure_helper(struct state_video_decoder *decoder, struct video_desc network_desc, struct pixfmt_desc comp_int_desc)
#define FRAMEBUFFER_NOT_READY(decoder)
#define ENCRYPTED_ERR
constexpr int PADDING
#define NOT_ENCRYPTED_ERR
#define MOD_NAME
static void reconfigure_if_needed(struct state_video_decoder *decoder, struct video_desc network_desc, struct pixfmt_desc comp_int_desc)
static void check_for_mode_change(struct state_video_decoder *decoder, const uint32_t *hdr)
static void decoder_set_video_mode(struct state_video_decoder *decoder, enum video_mode video_mode)
static void wait_for_framebuffer_swap(struct state_video_decoder *decoder)
#define ERROR_GOTO_CLEANUP
#define max(a, b)
struct tile * vf_get_tile(struct video_frame *buf, int pos)
Returns pointer to n-th tile from video frame Equivalent to &video_frame::tiles[pos].

References state_video_decoder::buffer_swapped, video_frame::callbacks, check_for_mode_change(), cleanup(), state_video_decoder::control, count, coded_data::data, tile::data, video_frame_callbacks::data_deleter, tile::data_len, state_video_decoder::dec_funcs, vcodec_state::decoded, vcodec_state::decoder, decoder_set_video_mode(), state_video_decoder::decoder_type, openssl_decrypt_info::decrypt, state_video_decoder::decrypt, state_video_decoder::display, state_video_decoder::display_desc, ENCRYPTED_ERR, ERROR_GOTO_CLEANUP, pbuf_stats::expected_pkts_cum, video_frame::fec_params, state_video_decoder::fec_queue, fec::fec_type_from_pt(), video_desc::fps, frame, state_video_decoder::frame, FRAMEBUFFER_NOT_READY, get_video_mode_description(), guess_video_mode(), handle_error(), len, state_video_decoder::line_decoder, state_video_decoder::lock, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, LOG_LEVEL_WARNING, log_msg(), log_msg_once(), max, vcodec_state::max_frame_size, state_video_decoder::max_substreams, state_video_decoder::merged_fb, MOD_NAME, MODE_AES128_MAX, MODE_AES128_NONE, state_video_decoder::msg_queue, NOT_ENCRYPTED_ERR, coded_data::nxt, offset, PADDING, synchronized_queue< T, max_len >::pop(), timed_message< log_level >::print(), PT_ENCRYPT_VIDEO, PT_ENCRYPT_VIDEO_LDGM, PT_ENCRYPT_VIDEO_RS, PT_Unassign_Type95, PT_VIDEO, PT_VIDEO_HAS_FEC, PT_VIDEO_IS_ENCRYPTED, PT_VIDEO_LDGM, PT_VIDEO_RS, synchronized_queue< T, max_len >::push(), pbuf_stats::received_pkts_cum, state_video_decoder::received_vid_desc, reconfigure_helper(), reconfigure_if_needed(), RTP_MAX_PACKET_LEN, rtp_packet, state_video_decoder::slow_msg, video_frame::ssrc, start(), state_video_decoder::stats, video_frame::tiles, video_frame::timestamp, to_fourcc, vf_alloc(), vf_data_deleter(), vf_free(), vf_get_tile(), state_video_decoder::video_mode, VIDEO_UNKNOWN, wait_for_framebuffer_swap(), and video_desc::width.

Referenced by ultragrid_rtp_video_rxtx::receiver_loop().

Here is the call graph for this function:

◆ parse_video_hdr()

bool parse_video_hdr ( const uint32_t * hdr,
struct video_desc * desc )

Definition at line 1405 of file video_decoders.cpp.

1406{
1407 uint32_t tmp;
1408 int fps_pt, fpsd, fd, fi;
1409
1410 tmp = ntohl(hdr[0]);
1411 desc->tile_count = (tmp >> 22) + 1; // a bit hacky - assuming this packet is from last substream
1412
1413 desc->width = ntohl(hdr[3]) >> 16;
1414 desc->height = ntohl(hdr[3]) & 0xffff;
1417 log_msg(LOG_LEVEL_ERROR, "Unknown FourCC \"%.4s\"!\n",
1418 (const char *)&hdr[4]);
1419 return false;
1420 }
1421
1422 tmp = ntohl(hdr[5]);
1423 desc->interlacing = (enum interlacing_t) (tmp >> 29);
1424 fps_pt = (tmp >> 19) & 0x3ff;
1425 fpsd = (tmp >> 15) & 0xf;
1426 fd = (tmp >> 14) & 0x1;
1427 fi = (tmp >> 13) & 0x1;
1428
1429 desc->fps = compute_fps(fps_pt, fpsd, fd, fi);
1430
1431 if (desc->fps == -1) {
1432 log_msg_once(LOG_LEVEL_WARNING, to_fourcc('U', 'F', 'P', 'S'), MOD_NAME "Unsupported FPS received (newer UG?), setting to 30.\n");
1433 desc->fps = 30.0;
1434 }
1435
1436 return true;
1437}
struct video_desc desc
unsigned int tile_count
Definition types.h:185
codec_t color_spec
Definition types.h:182
enum interlacing_t interlacing
Definition types.h:184
unsigned int height
height of every tile (!)
Definition types.h:180
interlacing_t
Definition types.h:163
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
codec_t get_codec_from_fcc(uint32_t fourcc)
double compute_fps(int fps, int fpsd, int fd, int fi)
Computes FPS as a double from packet fields.

References video_desc::color_spec, compute_fps(), desc, video_desc::fps, get_codec_from_fcc(), video_desc::height, video_desc::interlacing, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), log_msg_once(), MOD_NAME, video_desc::tile_count, to_fourcc, VIDEO_CODEC_NONE, and video_desc::width.

Referenced by check_for_mode_change(), decode_yuri_video_frame(), and fec_thread().

Here is the call graph for this function:

◆ video_decoder_destroy()

void video_decoder_destroy ( struct state_video_decoder * decoder)

Destroys decoder created with decoder_init()

Parameters
decoderdecoder to be destroyed. If NULL, no action is performed.

Definition at line 976 of file video_decoders.cpp.

977{
978 if(!decoder)
979 return;
980
981 if (decoder->dec_funcs) {
982 decoder->dec_funcs->destroy(decoder->decrypt);
983 }
984
986
987 cleanup(decoder);
988
989 free(decoder->disp_supported_il);
990
991 delete decoder;
992}
void video_decoder_remove_display(struct state_video_decoder *decoder)
This removes display from current decoder.
void(* destroy)(struct openssl_decrypt *state)
enum interlacing_t * disp_supported_il
display supported interlacing mode

References cleanup(), state_video_decoder::dec_funcs, state_video_decoder::decrypt, openssl_decrypt_info::destroy, state_video_decoder::disp_supported_il, and video_decoder_remove_display().

Referenced by ultragrid_rtp_video_rxtx::destroy_video_decoder().

Here is the call graph for this function:

◆ video_decoder_init()

struct state_video_decoder * video_decoder_init ( struct module * parent,
enum video_mode,
struct display * display,
const char * encryption )

◆ video_decoder_register_display()

bool video_decoder_register_display ( struct state_video_decoder * decoder,
struct display * display )

Registers video display to be used for displaying decoded video frames.

No display should be managed by this decoder when this function is called.

See also
decoder_remove_display
Parameters
decoderdecoder state
displaynew display to be registered
Returns
whether registration was successful

Definition at line 859 of file video_decoders.cpp.

860{
861 assert(display != NULL);
862 assert(decoder->display == NULL);
863
864 int ret;
865
866 decoder->display = display;
867
868 codec_t native_codecs[VIDEO_CODEC_COUNT];
869 size_t len = sizeof native_codecs;
870 ret = display_ctl_property(decoder->display, DISPLAY_PROPERTY_CODECS, native_codecs, &len);
871 decoder->native_codecs.clear();
872 if (!ret) {
873 log_msg(LOG_LEVEL_ERROR, "Failed to query codecs from video display.\n");
874 } else {
875 for (size_t i = 0; i < len / sizeof(codec_t); ++i) {
876 decoder->native_codecs.push_back(native_codecs[i]);
877 }
878 }
879 if (get_commandline_param("decoder-use-codec")) {
880 const char *codec_str = get_commandline_param("decoder-use-codec");
881 bool blacklist_codec = false;
882 if (codec_str[0] == '!') {
883 blacklist_codec = true;
884 codec_str += 1;
885 }
886 codec_t req_codec = get_codec_from_name(codec_str);
887 if ("help"s == codec_str) {
888 LOG(LOG_LEVEL_NOTICE) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
889 return false;
890 }
891 if (req_codec == VIDEO_CODEC_NONE) {
892 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong decoder codec spec: %s.\n", codec_str);
893 LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
894 return false;
895 }
896 if (blacklist_codec) {
897 auto to_erase = find(decoder->native_codecs.begin(),
898 decoder->native_codecs.end(),
899 req_codec);
900 if (to_erase != decoder->native_codecs.end()) {
901 decoder->native_codecs.erase(to_erase);
902 }
903 } else if (find(decoder->native_codecs.begin(),
904 decoder->native_codecs.end(),
905 req_codec) != end(decoder->native_codecs)) {
906 decoder->native_codecs.clear();
907 decoder->native_codecs.push_back(req_codec);
908 } else {
909 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Display doesn't support requested codec: %s.\n", codec_str);
910 LOG(LOG_LEVEL_INFO) << MOD_NAME << "Supported codecs for current display are: " << codec_list_to_str(decoder->native_codecs) << "\n";
911 return false;
912 }
913 }
914
915 free(decoder->disp_supported_il);
916 decoder->disp_supported_il_cnt = 20 * sizeof(enum interlacing_t);
917 decoder->disp_supported_il = (enum interlacing_t*) calloc(decoder->disp_supported_il_cnt,
918 sizeof(enum interlacing_t));
920 if(ret) {
921 decoder->disp_supported_il_cnt /= sizeof(enum interlacing_t);
922 } else {
923 enum interlacing_t tmp[] = { PROGRESSIVE, INTERLACED_MERGED, SEGMENTED_FRAME}; /* default if not said othervise */
924 memcpy(decoder->disp_supported_il, tmp, sizeof(tmp));
925 decoder->disp_supported_il_cnt = sizeof(tmp) / sizeof(enum interlacing_t);
926 }
927
929
930 return true;
931}
codec_t get_codec_from_name(const char *name)
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
bool display_ctl_property(struct display *d, int property, void *val, size_t *len)
Gets property from video display.
@ DISPLAY_PROPERTY_SUPPORTED_IL_MODES
display supported interlacing modes - enum interlacing_t[]
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
const char * get_commandline_param(const char *key)
Definition host.cpp:894
This struct represents initialized video display state.
size_t disp_supported_il_cnt
count of disp_supported_il
vector< codec_t > native_codecs
list of display native codecs
@ PROGRESSIVE
progressive frame
Definition types.h:164
@ SEGMENTED_FRAME
Segmented frame. Contains the same data as progressive frame.
Definition types.h:168
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
Definition types.h:167
codec_t
Definition types.h:65
@ VIDEO_CODEC_COUNT
count of known video codecs (including VIDEO_CODEC_NONE)
Definition types.h:108
static auto codec_list_to_str(vector< codec_t > const &codecs)
static void video_decoder_start_threads(struct state_video_decoder *decoder)
starts decompress and ldmg threads

References codec_list_to_str(), state_video_decoder::disp_supported_il, state_video_decoder::disp_supported_il_cnt, state_video_decoder::display, display_ctl_property(), DISPLAY_PROPERTY_CODECS, DISPLAY_PROPERTY_SUPPORTED_IL_MODES, get_codec_from_name(), get_commandline_param(), INTERLACED_MERGED, len, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, log_msg(), MOD_NAME, state_video_decoder::native_codecs, PROGRESSIVE, SEGMENTED_FRAME, VIDEO_CODEC_COUNT, VIDEO_CODEC_NONE, and video_decoder_start_threads().

Referenced by video_decoder_init().

Here is the call graph for this function:

◆ video_decoder_remove_display()

void video_decoder_remove_display ( struct state_video_decoder * decoder)

This removes display from current decoder.

From now on, no video frames will be decoded with current decoder.

See also
decoder_register_display - the counterpart of this functon
Parameters
decoderdecoder from which will the decoder be removed

Definition at line 941 of file video_decoders.cpp.

942{
943 if (decoder->display) {
945 if (decoder->frame) {
946 display_put_frame(decoder->display, decoder->frame, PUTF_DISCARD);
947 decoder->frame = NULL;
948 }
949 decoder->display = NULL;
950 memset(&decoder->display_desc, 0, sizeof(decoder->display_desc));
951 }
952}
bool display_put_frame(struct display *d, struct video_frame *frame, long long timeout_ns)
Puts filled video frame. After calling this function, video frame cannot be used.
#define PUTF_DISCARD
static void video_decoder_stop_threads(struct state_video_decoder *decoder)
This function stops running threads.

References state_video_decoder::display, state_video_decoder::display_desc, display_put_frame(), state_video_decoder::frame, PUTF_DISCARD, and video_decoder_stop_threads().

Referenced by ultragrid_rtp_video_rxtx::remove_display_from_decoders(), and video_decoder_destroy().

Here is the call graph for this function: