1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RTP Packetization of RAW video (RFC4175)
3cabdff1aSopenharmony_ci * Copyright (c) 2021 Limin Wang
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci#include "avformat.h"
22cabdff1aSopenharmony_ci#include "rtpenc.h"
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_civoid ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field)
25cabdff1aSopenharmony_ci{
26cabdff1aSopenharmony_ci    RTPMuxContext *s = s1->priv_data;
27cabdff1aSopenharmony_ci    int width = s1->streams[0]->codecpar->width;
28cabdff1aSopenharmony_ci    int height = s1->streams[0]->codecpar->height;
29cabdff1aSopenharmony_ci    int xinc, yinc, pgroup;
30cabdff1aSopenharmony_ci    int i = 0;
31cabdff1aSopenharmony_ci    int offset = 0;
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci    s->timestamp = s->cur_timestamp;
34cabdff1aSopenharmony_ci    switch (s1->streams[0]->codecpar->format) {
35cabdff1aSopenharmony_ci        case AV_PIX_FMT_UYVY422:
36cabdff1aSopenharmony_ci            xinc = 2;
37cabdff1aSopenharmony_ci            yinc = 1 << interlaced;
38cabdff1aSopenharmony_ci            pgroup = 4;
39cabdff1aSopenharmony_ci            break;
40cabdff1aSopenharmony_ci        case AV_PIX_FMT_YUV422P10:
41cabdff1aSopenharmony_ci            xinc = 2;
42cabdff1aSopenharmony_ci            yinc = 1 << interlaced;
43cabdff1aSopenharmony_ci            pgroup = 5;
44cabdff1aSopenharmony_ci            break;
45cabdff1aSopenharmony_ci        case AV_PIX_FMT_YUV420P:
46cabdff1aSopenharmony_ci            xinc = 4;
47cabdff1aSopenharmony_ci            yinc = 1 << interlaced;
48cabdff1aSopenharmony_ci            pgroup = 6;
49cabdff1aSopenharmony_ci            break;
50cabdff1aSopenharmony_ci        case AV_PIX_FMT_RGB24:
51cabdff1aSopenharmony_ci            xinc = 1;
52cabdff1aSopenharmony_ci            yinc = 1 << interlaced;
53cabdff1aSopenharmony_ci            pgroup = 3;
54cabdff1aSopenharmony_ci            break;
55cabdff1aSopenharmony_ci        case AV_PIX_FMT_BGR24:
56cabdff1aSopenharmony_ci            xinc = 1;
57cabdff1aSopenharmony_ci            yinc = 1 << interlaced;
58cabdff1aSopenharmony_ci            pgroup = 3;
59cabdff1aSopenharmony_ci            break;
60cabdff1aSopenharmony_ci        default:
61cabdff1aSopenharmony_ci            return;
62cabdff1aSopenharmony_ci    }
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    while (i < height) {
65cabdff1aSopenharmony_ci        int left = s->max_payload_size;
66cabdff1aSopenharmony_ci        uint8_t *dest = s->buf;
67cabdff1aSopenharmony_ci        uint8_t *headers;
68cabdff1aSopenharmony_ci        const int head_size = 6;
69cabdff1aSopenharmony_ci        int next_line;
70cabdff1aSopenharmony_ci        int length, cont, pixels;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci        /* Extended Sequence Number */
73cabdff1aSopenharmony_ci        *dest++ = 0;
74cabdff1aSopenharmony_ci        *dest++ = 0;
75cabdff1aSopenharmony_ci        left   -= 2;
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ci        headers = dest;
78cabdff1aSopenharmony_ci        do {
79cabdff1aSopenharmony_ci            int l_line;
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci            pixels = width - offset;
82cabdff1aSopenharmony_ci            length = (pixels * pgroup) / xinc;
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci            left -= head_size;
85cabdff1aSopenharmony_ci            if (left >= length) {
86cabdff1aSopenharmony_ci                next_line = 1;
87cabdff1aSopenharmony_ci            } else {
88cabdff1aSopenharmony_ci                pixels = (left / pgroup) * xinc;
89cabdff1aSopenharmony_ci                length = (pixels * pgroup) / xinc;
90cabdff1aSopenharmony_ci                next_line = 0;
91cabdff1aSopenharmony_ci            }
92cabdff1aSopenharmony_ci            left -= length;
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci            /* Length */
95cabdff1aSopenharmony_ci            *dest++ = (length >> 8) & 0xff;
96cabdff1aSopenharmony_ci            *dest++ = length & 0xff;
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci            /* Line No */
99cabdff1aSopenharmony_ci            l_line = i >> interlaced;
100cabdff1aSopenharmony_ci            *dest++ = ((l_line >> 8) & 0x7f) | ((field << 7) & 0x80);
101cabdff1aSopenharmony_ci            *dest++ = l_line & 0xff;
102cabdff1aSopenharmony_ci            if (next_line) i += yinc;
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci            cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00;
105cabdff1aSopenharmony_ci            /* Offset and Continuation marker */
106cabdff1aSopenharmony_ci            *dest++ = ((offset >> 8) & 0x7f) | cont;
107cabdff1aSopenharmony_ci            *dest++ = offset & 0xff;
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci            if (next_line)
110cabdff1aSopenharmony_ci                offset  = 0;
111cabdff1aSopenharmony_ci            else
112cabdff1aSopenharmony_ci                offset += pixels;
113cabdff1aSopenharmony_ci        } while (cont);
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci        do {
116cabdff1aSopenharmony_ci            int l_field;
117cabdff1aSopenharmony_ci            int l_line;
118cabdff1aSopenharmony_ci            int l_off;
119cabdff1aSopenharmony_ci            int copy_offset;
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci            length    = (headers[0] << 8) | headers[1];
122cabdff1aSopenharmony_ci            l_field   = (headers[2] & 0x80) >> 7;
123cabdff1aSopenharmony_ci            l_line    = ((headers[2] & 0x7f) << 8) | headers[3];
124cabdff1aSopenharmony_ci            l_off     = ((headers[4] & 0x7f) << 8) | headers[5];
125cabdff1aSopenharmony_ci            cont      = headers[4] & 0x80;
126cabdff1aSopenharmony_ci            headers  += head_size;
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci            if (interlaced)
129cabdff1aSopenharmony_ci                l_line = 2 * l_line + l_field;
130cabdff1aSopenharmony_ci            copy_offset = (l_line * width + l_off) * pgroup / xinc;
131cabdff1aSopenharmony_ci            if (copy_offset + length > size)
132cabdff1aSopenharmony_ci                break;
133cabdff1aSopenharmony_ci            memcpy (dest, buf + copy_offset, length);
134cabdff1aSopenharmony_ci            dest += length;
135cabdff1aSopenharmony_ci        } while (cont);
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci        ff_rtp_send_data (s1, s->buf, s->max_payload_size - left, i >= height);
138cabdff1aSopenharmony_ci    }
139cabdff1aSopenharmony_ci}
140