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