📄 rfc2435.txt
字号:
? RTP/JPEG data payload to produce a JPEG compressed image in
? interchange format (except for possible trailing garbage and
? absence of an EOI marker to terminate the scan).
*/
int MakeHeaders(u_char *p, int type, int w, int h, u_char *lqt,
u_char *cqt, u_short dri)
{
u_char *start = p;
/* convert from blocks to pixels */
w <<= 3;
h <<= 3;
*p++ = 0xff;
*p++ = 0xd8; /* SOI */
p = MakeQuantHeader(p, lqt, 0);
p = MakeQuantHeader(p, cqt, 1);
if (dri != 0)
p = MakeDRIHeader(p, dri);
*p++ = 0xff;
*p++ = 0xc0; /* SOF */
*p++ = 0; /* length msb */
*p++ = 17; /* length lsb */
*p++ = 8; /* 8-bit precision */
*p++ = h >> 8; /* height msb */
*p++ = h; /* height lsb */
*p++ = w >> 8; /* width msb */
*p++ = w; /* wudth lsb */
*p++ = 3; /* number of components */
*p++ = 0; /* comp 0 */
if (type == 0)
*p++ = 0x21; /* hsamp = 2, vsamp = 1 */
else
*p++ = 0x22; /* hsamp = 2, vsamp = 2 */
*p++ = 0; /* quant table 0 */
*p++ = 1; /* comp 1 */
*p++ = 0x11; /* hsamp = 1, vsamp = 1 */
*p++ = 1; /* quant table 1 */
*p++ = 2; /* comp 2 */
*p++ = 0x11; /* hsamp = 1, vsamp = 1 */
*p++ = 1; /* quant table 1 */
p = MakeHuffmanHeader(p, lum_dc_codelens,
sizeof(lum_dc_codelens),
lum_dc_symbols,
sizeof(lum_dc_symbols), 0, 0);
p = MakeHuffmanHeader(p, lum_ac_codelens,
sizeof(lum_ac_codelens),
lum_ac_symbols,
sizeof(lum_ac_symbols), 0, 1);
p = MakeHuffmanHeader(p, chm_dc_codelens,
sizeof(chm_dc_codelens),
chm_dc_symbols,
sizeof(chm_dc_symbols), 1, 0);
p = MakeHuffmanHeader(p, chm_ac_codelens,
sizeof(chm_ac_codelens),
chm_ac_symbols,
sizeof(chm_ac_symbols), 1, 1);
*p++ = 0xff;
*p++ = 0xda; /* SOS */
*p++ = 0; /* length msb */
*p++ = 12; /* length lsb */
*p++ = 3; /* 3 components */
*p++ = 0; /* comp 0 */
*p++ = 0; /* Success table 0 */
*p++ = 1; /* comp 1 */
*p++ = 0x11; /* Success table 1 */
*p++ = 2; /* comp 2 */
*p++ = 0x11; /* Success table 1 */
*p++ = 0; /* first DCT coeff */
*p++ = 63; /* last DCT coeff */
*p++ = 0; /* Successive approx. */
return (p – start);
};
附录 C
下面这段代码用来阐明RTP/JPEG数据包分片和头的生成过程。
For clarity and brevity, the structure definitions are only valid for
32-bit big-endian (most significant octet first) architectures. Bit
fields are assumed to be packed tightly in big-endian bit order, with
no additional padding. Modifications would be required to construct a
portable implementation.
/*
? RTP data header from RFC1889
*/
typedef struct {
unsigned int version:2; /* protocol version */
unsigned int p:1; /* padding flag */
unsigned int x:1; /* header extension flag */
unsigned int cc:4; /* CSRC count */
unsigned int m:1; /* marker bit */
unsigned int pt:7; /* payload type */
u_int16 seq; /* sequence number */
u_int32 ts; /* timestamp */
u_int32 ssrc; /* synchronization source */
u_int32 csrc[1]; /* optional CSRC list */
} rtp_hdr_t;
#define RTP_HDR_SZ 12
/* The following definition is from RFC1890 */
#define RTP_PT_JPEG 26
struct jpeghdr {
unsigned int tspec:8; /* type-specific field */
unsigned int off:24; /* fragment byte offset */
u_int8 type; /* id of jpeg decoder params */
u_int8 q; /* quantization factor (or table id) */
u_int8 width; /* frame width in 8 pixel blocks */
u_int8 height; /* frame height in 8 pixel blocks */
};
struct jpeghdr_rst {
u_int16 dri;
unsigned int f:1;
unsigned int l:1;
unsigned int count:14;
};
struct jpeghdr_qtable {
u_int8 mbz;
u_int8 precision;
u_int16 length;
};
#define RTP_JPEG_RESTART 0x40
/* Procedure SendFrame:
*
? Arguments:
? start_seq: The sequence number for the first packet of the current
? frame.
? ts: RTP timestamp for the current frame
? ssrc: RTP SSRC value
? jpeg_data: Huffman encoded JPEG scan data
? len: Length of the JPEG scan data
? type: The value the RTP/JPEG type field should be set to
? typespec: The value the RTP/JPEG type-specific field should be set
? to
? width: The width in pixels of the JPEG image
? height: The height in pixels of the JPEG image
? dri: The number of MCUs between restart markers (or 0 if there
? are no restart markers in the data
? q: The Q factor of the data, to be specified using the Independent
? JPEG group's algorithm if 1 <= q <= 99, specified explicitly
? with lqt and cqt if q >= 128, or undefined otherwise.
? lqt: The quantization table for the luminance channel if q >= 128
? cqt: The quantization table for the chrominance channels if
? q >= 128
*
? Return value:
? the sequence number to be sent for the first packet of the next
? frame.
*
? The following are assumed to be defined:
*
* PACKET_SIZE - The size of the outgoing packet
? send_packet(u_int8 *data, int len) - Sends the packet to the network
*/
u_int16 SendFrame(u_int16 start_seq, u_int32 ts, u_int32 ssrc,
u_int8 *jpeg_data, int len, u_int8 type,
u_int8 typespec, int width, int height, int dri,
u_int8 q, u_int8 *lqt, u_int8 *cqt) {
rtp_hdr_t rtphdr;
struct jpeghdr jpghdr;
struct jpeghdr_rst rsthdr;
struct jpeghdr_qtable qtblhdr;
u_int8 packet_buf[PACKET_SIZE];
u_int8 *ptr;
int bytes_left = len;
int seq = start_seq;
int pkt_len, data_len;
/* Initialize RTP header
*/
rtphdr.version = 2;
rtphdr.p = 0;
rtphdr.x = 0;
rtphdr.cc = 0;
rtphdr.m = 0;
rtphdr.pt = RTP_PT_JPEG;
rtphdr.seq = start_seq;
rtphdr.ts = ts;
rtphdr.ssrc = ssrc;
/* Initialize JPEG header
*/
jpghdr.tspec = typespec;
jpghdr.off = 0;
jpghdr.type = type | ((dri != 0) ? RTP_JPEG_RESTART : 0);
jpghdr.q = q;
jpghdr.width = width / 8;
jpghdr.height = height / 8;
/* Initialize DRI header
*/
if (dri != 0) {
rsthdr.dri = dri;
rsthdr.f = 1; /* This code does not align Ris */
rsthdr.l = 1;
rsthdr.count = 0x3fff;
}
/* Initialize quantization table header
*/
if (q >= 128) {
qtblhdr.mbz = 0;
qtblhdr.precision = 0; /* This code uses 8 bit tables only */
qtblhdr.length = 128; /* 2 64-byte tables */
}
while (bytes_left > 0) {
ptr = packet_buf + RTP_HDR_SZ;
memcpy(ptr, &jpghdr, sizeof(jpghdr));
ptr += sizeof(jpghdr);
if (dri != 0) {
memcpy(ptr, &rsthdr, sizeof(rsthdr));
ptr += sizeof(rsthdr);
}
if (q >= 128 && jpghdr.off == 0) {
memcpy(ptr, &qtblhdr, sizeof(qtblhdr));
ptr += sizeof(qtblhdr);
memcpy(ptr, lqt, 64);
ptr += 64;
memcpy(ptr, cqt, 64);
ptr += 64;
}
data_len = PACKET_SIZE – (ptr – packet_buf);
if (data_len >= bytes_left) {
data_len = bytes_left;
rtphdr.m = 1;
}
memcpy(packet_buf, &rtphdr, RTP_HDR_SZ);
memcpy(ptr, jpeg_data + jpghdr.off, data_len);
send_packet(packet_buf, (ptr – packet_buf) + data_len);
jpghdr.off += data_len;
bytes_left -= data_len;
rtphdr.seq++;
}
return rtphdr.seq;
}
附录 D
这一部分给出了本文档相对于RFC 2035的改动。这些改动着眼于尽可能保持新版本对于
旧版本的兼容性。事实上,很多已经废弃的约定仍然能够在新版中正常地解码。尽管如此,
我们仍然强烈反对在新版中使用一些旧地约定。
o 类型0和类型1现在可以编码隔行扫描的视频图象,用类型特定域中的两个比特给
出指示即可。参见4.1节。
o JPEG工作组曾经就如何更灵活地描述JPEG量化表发生过争论。本备忘录允许通过使
用一个可选地量化表头来显式地描述表系数。这些内容在节3.1.8和4.2中讨论。
o 在RFC 2035中,在类型域中描述复位标记的信息,这样就很难再加入新的类型。并
且,类型特定域用于记录复位计数,这样其它的一些类型特定信息就无法编码。在
本备忘录中,复位标记的指示移到了类型域中的一个特定比特位,并且加入了可选
头来编码一些必要的额外信息,而把类型特定域留出来用于它本来的用途。对于部
分帧解码的处理提高了码流的健壮性,能够对抗一定程度的丢包。详细信息参见
3.1.7和4.4。
版权声明
版权归Internet协会所有(1998)。保留所有权利。
本文及其译本可以提供给其他任何人,可以准备继续进行注释,可以继续拷贝、出版、发
布,无论是全部还是部分,没有任何形式的限制,不过要在所有这样的拷贝和后续工作中提
供上述声明和本段文字。无论如何,本文档本身不可以做任何的修改,比如删除版权声明或
是关于因特耐特协会、其他的因特耐特组织的参考资料等。除了是为了开发Internet标准的
需要,或是需要把它翻译成除英语外的其他语言的时候,在这种情况下,在Internet标准程
序中的版权定义必须被附加其中。
上面提到的有限授权允许永远不会被Internet协会或它的继承者或它的下属机构废除。
本文档和包含在其中的信息以"As is"提供给读者,Internet社区和Internet工程任务
组不做任何担保、解释和暗示,包括该信息使用不破坏任何权利或者任何可商用性担保或特
定目的。
RFC2435—RTP Payload Format for JPEG-compressed Video 针对JPEG压缩视频的RTP荷载格式
1
RFC文档中文翻译计划
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -