blob: 085204fa646dc8c8aa2997be13bb5fd5521abbc4
1 | /* |
2 | * RTP packetizer for VC-2 HQ payload format (draft version 1) - experimental |
3 | * Copyright (c) 2016 Thomas Volkert <thomas@netzeal.de> |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "libavutil/intreadwrite.h" |
23 | #include "libavcodec/dirac.h" |
24 | #include "libavcodec/get_bits.h" |
25 | #include "libavcodec/golomb.h" |
26 | |
27 | #include "avformat.h" |
28 | #include "rtpenc.h" |
29 | |
30 | #define RTP_VC2HQ_PL_HEADER_SIZE 4 |
31 | |
32 | #define DIRAC_DATA_UNIT_HEADER_SIZE 13 |
33 | #define DIRAC_PIC_NR_SIZE 4 |
34 | #define DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT 0xEC |
35 | |
36 | static void send_packet(AVFormatContext *ctx, uint8_t parse_code, int info_hdr_size, const uint8_t *buf, int size, int i, int f, int rtp_m) |
37 | { |
38 | RTPMuxContext *rtp_ctx = ctx->priv_data; |
39 | |
40 | AV_WB16(&rtp_ctx->buf[0], 0); /* extended sequence number */ |
41 | AV_WB8 (&rtp_ctx->buf[2], i ? (f ? (0x03) : (0x02)) : 0x00); /* flags: interlaced, second field */ |
42 | AV_WB8 (&rtp_ctx->buf[3], parse_code); |
43 | if (size > 0) |
44 | memcpy(&rtp_ctx->buf[4 + info_hdr_size], buf, size); |
45 | ff_rtp_send_data(ctx, rtp_ctx->buf, RTP_VC2HQ_PL_HEADER_SIZE + info_hdr_size + size, rtp_m); |
46 | } |
47 | |
48 | static void send_picture(AVFormatContext *ctx, const uint8_t *buf, int size, int interlaced) |
49 | { |
50 | RTPMuxContext *rtp_ctx = ctx->priv_data; |
51 | GetBitContext gc; |
52 | int lvl, second_field; |
53 | uint32_t pic_nr, wavelet_depth, prefix_bytes, size_scaler; |
54 | uint16_t frag_len; |
55 | char *info_hdr = &rtp_ctx->buf[4]; |
56 | |
57 | pic_nr = AV_RB32(&buf[0]); |
58 | buf += DIRAC_PIC_NR_SIZE; |
59 | size -= DIRAC_PIC_NR_SIZE; |
60 | second_field = interlaced && (pic_nr & 0x01); |
61 | |
62 | init_get_bits(&gc, buf, 8 * size); |
63 | get_interleaved_ue_golomb(&gc); /* wavelet_idx */ |
64 | wavelet_depth = get_interleaved_ue_golomb(&gc); |
65 | get_interleaved_ue_golomb(&gc); /* num_x */ |
66 | get_interleaved_ue_golomb(&gc); /* num_y */ |
67 | prefix_bytes = get_interleaved_ue_golomb(&gc); |
68 | size_scaler = get_interleaved_ue_golomb(&gc); |
69 | /* pass the quantization matrices */ |
70 | get_interleaved_ue_golomb(&gc); |
71 | for(lvl = 0; lvl < wavelet_depth; lvl++) |
72 | { |
73 | get_interleaved_ue_golomb(&gc); |
74 | get_interleaved_ue_golomb(&gc); |
75 | get_interleaved_ue_golomb(&gc); |
76 | } |
77 | |
78 | frag_len = (get_bits_count(&gc) + 7) / 8; /* length of transform parameters */ |
79 | |
80 | AV_WB32(&info_hdr[ 0], pic_nr); |
81 | AV_WB16(&info_hdr[ 4], prefix_bytes); |
82 | AV_WB16(&info_hdr[ 6], size_scaler); |
83 | AV_WB16(&info_hdr[ 8], frag_len); |
84 | AV_WB16(&info_hdr[10], 0 /* nr. of slices */); |
85 | send_packet(ctx, DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT, 12, buf, frag_len, interlaced, second_field, 0); |
86 | buf += frag_len; |
87 | size -= frag_len; |
88 | |
89 | while (size > 0) { |
90 | frag_len = FFMIN(rtp_ctx->max_payload_size - 20 /* pl header */, size); |
91 | AV_WB16(&info_hdr[ 8], frag_len); |
92 | AV_WB16(&info_hdr[10], 1 /* nr. of slices */); |
93 | AV_WB16(&info_hdr[12], 0 /* slice x */); |
94 | AV_WB16(&info_hdr[14], 0 /* slice y */); |
95 | |
96 | size -= frag_len; |
97 | send_packet(ctx, DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT, 16, buf, frag_len, interlaced, second_field, size > 0 ? 0 : 1); |
98 | buf += frag_len; |
99 | } |
100 | } |
101 | |
102 | void ff_rtp_send_vc2hq(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size, int interlaced) |
103 | { |
104 | const uint8_t *end = frame_buf + frame_size; |
105 | const uint8_t *unit = frame_buf; |
106 | uint8_t parse_code; |
107 | uint32_t unit_size; |
108 | |
109 | while (unit < end) { |
110 | parse_code = unit[4]; |
111 | unit_size = AV_RB32(&unit[5]); |
112 | |
113 | switch (parse_code) { |
114 | /* sequence header */ |
115 | /* end of sequence */ |
116 | case DIRAC_PCODE_SEQ_HEADER: |
117 | case DIRAC_PCODE_END_SEQ: |
118 | send_packet(ctx, parse_code, 0, unit + DIRAC_DATA_UNIT_HEADER_SIZE, unit_size - DIRAC_DATA_UNIT_HEADER_SIZE, 0, 0, 0); |
119 | break; |
120 | /* HQ picture */ |
121 | case DIRAC_PCODE_PICTURE_HQ: |
122 | send_picture(ctx, unit + DIRAC_DATA_UNIT_HEADER_SIZE, unit_size - DIRAC_DATA_UNIT_HEADER_SIZE, interlaced); |
123 | break; |
124 | /* parse codes without specification */ |
125 | case DIRAC_PCODE_AUX: |
126 | case DIRAC_PCODE_PAD: |
127 | break; |
128 | default: |
129 | avpriv_report_missing_feature(ctx, "VC-2 parse code %d", parse_code); |
130 | break; |
131 | } |
132 | unit += unit_size; |
133 | } |
134 | } |
135 |