1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RTP packetization for H.261 video (RFC 4587)
3cabdff1aSopenharmony_ci * Copyright (c) 2014 Thomas Volkert <thomas@homer-conferencing.com>
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
22cabdff1aSopenharmony_ci#include "avformat.h"
23cabdff1aSopenharmony_ci#include "rtpenc.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#define RTP_H261_HEADER_SIZE 4
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_cistatic const uint8_t *find_resync_marker_reverse(const uint8_t *av_restrict start,
28cabdff1aSopenharmony_ci                                                 const uint8_t *av_restrict end)
29cabdff1aSopenharmony_ci{
30cabdff1aSopenharmony_ci    const uint8_t *p = end - 1;
31cabdff1aSopenharmony_ci    start += 1; /* Make sure we never return the original start. */
32cabdff1aSopenharmony_ci    for (; p > start; p--) {
33cabdff1aSopenharmony_ci        if (p[0] == 0 && p[1] == 1)
34cabdff1aSopenharmony_ci            return p;
35cabdff1aSopenharmony_ci    }
36cabdff1aSopenharmony_ci    return end;
37cabdff1aSopenharmony_ci}
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_civoid ff_rtp_send_h261(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size)
40cabdff1aSopenharmony_ci{
41cabdff1aSopenharmony_ci    int cur_frame_size;
42cabdff1aSopenharmony_ci    int last_packet_of_frame;
43cabdff1aSopenharmony_ci    RTPMuxContext *rtp_ctx = ctx->priv_data;
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci    /* use the default 90 KHz time stamp */
46cabdff1aSopenharmony_ci    rtp_ctx->timestamp = rtp_ctx->cur_timestamp;
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci    /* continue as long as not all frame data is processed */
49cabdff1aSopenharmony_ci    while (frame_size > 0) {
50cabdff1aSopenharmony_ci        /*
51cabdff1aSopenharmony_ci         * encode the H.261 payload header according to section 4.1 of RFC 4587:
52cabdff1aSopenharmony_ci         * (uses 4 bytes between RTP header and H.261 stream per packet)
53cabdff1aSopenharmony_ci         *
54cabdff1aSopenharmony_ci         *    0                   1                   2                   3
55cabdff1aSopenharmony_ci         *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
56cabdff1aSopenharmony_ci         *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57cabdff1aSopenharmony_ci         *   |SBIT |EBIT |I|V| GOBN  |   MBAP  |  QUANT  |  HMVD   |  VMVD   |
58cabdff1aSopenharmony_ci         *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59cabdff1aSopenharmony_ci         *
60cabdff1aSopenharmony_ci         *      Start bit position (SBIT): 3 bits
61cabdff1aSopenharmony_ci         *      End bit position (EBIT): 3 bits
62cabdff1aSopenharmony_ci         *      INTRA-frame encoded data (I): 1 bit
63cabdff1aSopenharmony_ci         *      Motion Vector flag (V): 1 bit
64cabdff1aSopenharmony_ci         *      GOB number (GOBN): 4 bits
65cabdff1aSopenharmony_ci         *      Macroblock address predictor (MBAP): 5 bits
66cabdff1aSopenharmony_ci         *      Quantizer (QUANT): 5 bits
67cabdff1aSopenharmony_ci         *      Horizontal motion vector data (HMVD): 5 bits
68cabdff1aSopenharmony_ci         *      Vertical motion vector data (VMVD): 5 bits
69cabdff1aSopenharmony_ci         */
70cabdff1aSopenharmony_ci        rtp_ctx->buf[0] = 1; /* sbit=0, ebit=0, i=0, v=1 */
71cabdff1aSopenharmony_ci        rtp_ctx->buf[1] = 0; /* gobn=0, mbap=0 */
72cabdff1aSopenharmony_ci        rtp_ctx->buf[2] = 0; /* quant=0, hmvd=5 */
73cabdff1aSopenharmony_ci        rtp_ctx->buf[3] = 0; /* vmvd=0 */
74cabdff1aSopenharmony_ci        if (frame_size < 2 || frame_buf[0] != 0 || frame_buf[1] != 1) {
75cabdff1aSopenharmony_ci            /* A full, correct fix for this would be to make the H.261 encoder
76cabdff1aSopenharmony_ci             * support inserting extra GOB headers (triggered by setting e.g.
77cabdff1aSopenharmony_ci             * "-ps 1"), and including information about macroblock boundaries
78cabdff1aSopenharmony_ci             * (such as for h263_rfc2190). */
79cabdff1aSopenharmony_ci            av_log(ctx, AV_LOG_WARNING,
80cabdff1aSopenharmony_ci                   "RTP/H.261 packet not cut at a GOB boundary, not signaled correctly\n");
81cabdff1aSopenharmony_ci        }
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci        cur_frame_size = FFMIN(rtp_ctx->max_payload_size - RTP_H261_HEADER_SIZE, frame_size);
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci        /* look for a better place to split the frame into packets */
86cabdff1aSopenharmony_ci        if (cur_frame_size < frame_size) {
87cabdff1aSopenharmony_ci            const uint8_t *packet_end = find_resync_marker_reverse(frame_buf,
88cabdff1aSopenharmony_ci                                                                   frame_buf + cur_frame_size);
89cabdff1aSopenharmony_ci            cur_frame_size = packet_end - frame_buf;
90cabdff1aSopenharmony_ci        }
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci        /* calculate the "marker" bit for the RTP header */
93cabdff1aSopenharmony_ci        last_packet_of_frame = cur_frame_size == frame_size;
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_ci        /* complete and send RTP packet */
96cabdff1aSopenharmony_ci        memcpy(&rtp_ctx->buf[RTP_H261_HEADER_SIZE], frame_buf, cur_frame_size);
97cabdff1aSopenharmony_ci        ff_rtp_send_data(ctx, rtp_ctx->buf, RTP_H261_HEADER_SIZE + cur_frame_size, last_packet_of_frame);
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci        frame_buf  += cur_frame_size;
100cabdff1aSopenharmony_ci        frame_size -= cur_frame_size;
101cabdff1aSopenharmony_ci    }
102cabdff1aSopenharmony_ci}
103