Merge commit '81eec081afea9fc017a175581ceea7c420a0dfc3'
[ffmpeg.git] / libavformat / rtpenc_mpv.c
1 /*
2  * RTP packetization for MPEG video
3  * Copyright (c) 2002 Fabrice Bellard
4  * Copyright (c) 2007 Luca Abeni
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "libavcodec/internal.h"
24 #include "avformat.h"
25 #include "rtpenc.h"
26
27 /* NOTE: a single frame must be passed with sequence header if
28    needed. XXX: use slices. */
29 void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size)
30 {
31     RTPMuxContext *s = s1->priv_data;
32     int len, h, max_packet_size;
33     uint8_t *q;
34     const uint8_t *end = buf1 + size;
35     int begin_of_slice, end_of_slice, frame_type, temporal_reference;
36
37     max_packet_size = s->max_payload_size;
38     begin_of_slice = 1;
39     end_of_slice = 0;
40     frame_type = 0;
41     temporal_reference = 0;
42
43     while (size > 0) {
44         int begin_of_sequence;
45
46         begin_of_sequence = 0;
47         len = max_packet_size - 4;
48
49         if (len >= size) {
50             len = size;
51             end_of_slice = 1;
52         } else {
53             const uint8_t *r, *r1;
54             int start_code;
55
56             r1 = buf1;
57             while (1) {
58                 start_code = -1;
59                 r = avpriv_find_start_code(r1, end, &start_code);
60                 if((start_code & 0xFFFFFF00) == 0x100) {
61                     /* New start code found */
62                     if (start_code == 0x100) {
63                         frame_type = (r[1] & 0x38) >> 3;
64                         temporal_reference = (int)r[0] << 2 | r[1] >> 6;
65                     }
66                     if (start_code == 0x1B8) {
67                         begin_of_sequence = 1;
68                     }
69
70                     if (r - buf1 - 4 <= len) {
71                         /* The current slice fits in the packet */
72                         if (begin_of_slice == 0) {
73                             /* no slice at the beginning of the packet... */
74                             end_of_slice = 1;
75                             len = r - buf1 - 4;
76                             break;
77                         }
78                         r1 = r;
79                     } else {
80                         if ((r1 - buf1 > 4) && (r - r1 < max_packet_size)) {
81                             len = r1 - buf1 - 4;
82                             end_of_slice = 1;
83                         }
84                         break;
85                     }
86                 } else {
87                     break;
88                 }
89             }
90         }
91
92         h = 0;
93         h |= temporal_reference << 16;
94         h |= begin_of_sequence << 13;
95         h |= begin_of_slice << 12;
96         h |= end_of_slice << 11;
97         h |= frame_type << 8;
98
99         q = s->buf;
100         *q++ = h >> 24;
101         *q++ = h >> 16;
102         *q++ = h >> 8;
103         *q++ = h;
104
105         memcpy(q, buf1, len);
106         q += len;
107
108         /* 90kHz time stamp */
109         s->timestamp = s->cur_timestamp;
110         ff_rtp_send_data(s1, s->buf, q - s->buf, (len == size));
111
112         buf1 += len;
113         size -= len;
114         begin_of_slice = end_of_slice;
115         end_of_slice = 0;
116     }
117 }