1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RTP/Quicktime support.
3cabdff1aSopenharmony_ci * Copyright (c) 2009 Ronald S. Bultje
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/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * @brief Quicktime-style RTP support
25cabdff1aSopenharmony_ci * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "avformat.h"
29cabdff1aSopenharmony_ci#include "internal.h"
30cabdff1aSopenharmony_ci#include "avio_internal.h"
31cabdff1aSopenharmony_ci#include "rtp.h"
32cabdff1aSopenharmony_ci#include "rtpdec.h"
33cabdff1aSopenharmony_ci#include "isom.h"
34cabdff1aSopenharmony_ci#include "libavcodec/get_bits.h"
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_cistruct PayloadContext {
37cabdff1aSopenharmony_ci    AVPacket *pkt;
38cabdff1aSopenharmony_ci    int bytes_per_frame, remaining;
39cabdff1aSopenharmony_ci    uint32_t timestamp;
40cabdff1aSopenharmony_ci};
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_cistatic av_cold int qt_rtp_init(AVFormatContext *ctx, int st_index,
43cabdff1aSopenharmony_ci                               PayloadContext *qt)
44cabdff1aSopenharmony_ci{
45cabdff1aSopenharmony_ci    qt->pkt = av_packet_alloc();
46cabdff1aSopenharmony_ci    if (!qt->pkt)
47cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_ci    return 0;
50cabdff1aSopenharmony_ci}
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_cistatic int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
53cabdff1aSopenharmony_ci                               AVStream *st, AVPacket *pkt,
54cabdff1aSopenharmony_ci                               uint32_t *timestamp, const uint8_t *buf,
55cabdff1aSopenharmony_ci                               int len, uint16_t seq, int flags)
56cabdff1aSopenharmony_ci{
57cabdff1aSopenharmony_ci    FFIOContext pb0;
58cabdff1aSopenharmony_ci    AVIOContext *const pb = &pb0.pub;
59cabdff1aSopenharmony_ci    GetBitContext gb;
60cabdff1aSopenharmony_ci    int packing_scheme, has_payload_desc, has_packet_info, alen,
61cabdff1aSopenharmony_ci        has_marker_bit = flags & RTP_FLAG_MARKER,
62cabdff1aSopenharmony_ci        keyframe, ret;
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    if (qt->remaining) {
65cabdff1aSopenharmony_ci        int num = qt->pkt->size / qt->bytes_per_frame;
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_ci        if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0)
68cabdff1aSopenharmony_ci            return ret;
69cabdff1aSopenharmony_ci        pkt->stream_index = st->index;
70cabdff1aSopenharmony_ci        pkt->flags        = qt->pkt->flags;
71cabdff1aSopenharmony_ci        memcpy(pkt->data,
72cabdff1aSopenharmony_ci               &qt->pkt->data[(num - qt->remaining) * qt->bytes_per_frame],
73cabdff1aSopenharmony_ci               qt->bytes_per_frame);
74cabdff1aSopenharmony_ci        if (--qt->remaining == 0) {
75cabdff1aSopenharmony_ci            av_freep(&qt->pkt->data);
76cabdff1aSopenharmony_ci            qt->pkt->size = 0;
77cabdff1aSopenharmony_ci        }
78cabdff1aSopenharmony_ci        return qt->remaining > 0;
79cabdff1aSopenharmony_ci    }
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci    /**
82cabdff1aSopenharmony_ci     * The RTP payload is described in:
83cabdff1aSopenharmony_ci     * http://developer.apple.com/quicktime/icefloe/dispatch026.html
84cabdff1aSopenharmony_ci     */
85cabdff1aSopenharmony_ci    ret = init_get_bits(&gb, buf, len << 3);
86cabdff1aSopenharmony_ci    if (ret < 0)
87cabdff1aSopenharmony_ci        return ret;
88cabdff1aSopenharmony_ci    ffio_init_context(&pb0, (uint8_t*)buf, len, 0, NULL, NULL, NULL, NULL);
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    if (len < 4)
91cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci    skip_bits(&gb, 4); // version
94cabdff1aSopenharmony_ci    if ((packing_scheme = get_bits(&gb, 2)) == 0)
95cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
96cabdff1aSopenharmony_ci    keyframe            = get_bits1(&gb);
97cabdff1aSopenharmony_ci    has_payload_desc    = get_bits1(&gb);
98cabdff1aSopenharmony_ci    has_packet_info     = get_bits1(&gb);
99cabdff1aSopenharmony_ci    skip_bits(&gb, 23); // reserved:7, cache payload info:1, payload ID:15
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    if (has_payload_desc) {
102cabdff1aSopenharmony_ci        int data_len, pos, is_start, is_finish;
103cabdff1aSopenharmony_ci        uint32_t tag;
104cabdff1aSopenharmony_ci
105cabdff1aSopenharmony_ci        pos = get_bits_count(&gb) >> 3;
106cabdff1aSopenharmony_ci        if (pos + 12 > len)
107cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci        skip_bits(&gb, 2); // has non-I-frames:1, is sparse:1
110cabdff1aSopenharmony_ci        is_start  = get_bits1(&gb);
111cabdff1aSopenharmony_ci        is_finish = get_bits1(&gb);
112cabdff1aSopenharmony_ci        if (!is_start || !is_finish) {
113cabdff1aSopenharmony_ci            avpriv_request_sample(s, "RTP-X-QT with payload description "
114cabdff1aSopenharmony_ci                                  "split over several packets");
115cabdff1aSopenharmony_ci            return AVERROR_PATCHWELCOME;
116cabdff1aSopenharmony_ci        }
117cabdff1aSopenharmony_ci        skip_bits(&gb, 12); // reserved
118cabdff1aSopenharmony_ci        data_len = get_bits(&gb, 16);
119cabdff1aSopenharmony_ci
120cabdff1aSopenharmony_ci        avio_seek(pb, pos + 4, SEEK_SET);
121cabdff1aSopenharmony_ci        tag = avio_rl32(pb);
122cabdff1aSopenharmony_ci        if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
123cabdff1aSopenharmony_ci                 tag != MKTAG('v','i','d','e')) ||
124cabdff1aSopenharmony_ci            (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
125cabdff1aSopenharmony_ci                 tag != MKTAG('s','o','u','n')))
126cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
127cabdff1aSopenharmony_ci        avpriv_set_pts_info(st, 32, 1, avio_rb32(pb));
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci        if (pos + data_len > len)
130cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
131cabdff1aSopenharmony_ci        /* TLVs */
132cabdff1aSopenharmony_ci        while (avio_tell(pb) + 4 < pos + data_len) {
133cabdff1aSopenharmony_ci            int tlv_len = avio_rb16(pb);
134cabdff1aSopenharmony_ci            tag = avio_rl16(pb);
135cabdff1aSopenharmony_ci            if (avio_tell(pb) + tlv_len > pos + data_len)
136cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci#define MKTAG16(a,b) MKTAG(a,b,0,0)
139cabdff1aSopenharmony_ci            switch (tag) {
140cabdff1aSopenharmony_ci            case MKTAG16('s','d'): {
141cabdff1aSopenharmony_ci                MOVStreamContext *msc;
142cabdff1aSopenharmony_ci                void *priv_data = st->priv_data;
143cabdff1aSopenharmony_ci                int nb_streams = s->nb_streams;
144cabdff1aSopenharmony_ci                MOVContext *mc = av_mallocz(sizeof(*mc));
145cabdff1aSopenharmony_ci                if (!mc)
146cabdff1aSopenharmony_ci                    return AVERROR(ENOMEM);
147cabdff1aSopenharmony_ci                mc->fc = s;
148cabdff1aSopenharmony_ci                st->priv_data = msc = av_mallocz(sizeof(MOVStreamContext));
149cabdff1aSopenharmony_ci                if (!msc) {
150cabdff1aSopenharmony_ci                    av_free(mc);
151cabdff1aSopenharmony_ci                    st->priv_data = priv_data;
152cabdff1aSopenharmony_ci                    return AVERROR(ENOMEM);
153cabdff1aSopenharmony_ci                }
154cabdff1aSopenharmony_ci                /* ff_mov_read_stsd_entries updates stream s->nb_streams-1,
155cabdff1aSopenharmony_ci                 * so set it temporarily to indicate which stream to update. */
156cabdff1aSopenharmony_ci                s->nb_streams = st->index + 1;
157cabdff1aSopenharmony_ci                ff_mov_read_stsd_entries(mc, pb, 1);
158cabdff1aSopenharmony_ci                qt->bytes_per_frame = msc->bytes_per_frame;
159cabdff1aSopenharmony_ci                av_free(msc);
160cabdff1aSopenharmony_ci                av_free(mc);
161cabdff1aSopenharmony_ci                st->priv_data = priv_data;
162cabdff1aSopenharmony_ci                s->nb_streams = nb_streams;
163cabdff1aSopenharmony_ci                break;
164cabdff1aSopenharmony_ci            }
165cabdff1aSopenharmony_ci            default:
166cabdff1aSopenharmony_ci                avio_skip(pb, tlv_len);
167cabdff1aSopenharmony_ci                break;
168cabdff1aSopenharmony_ci            }
169cabdff1aSopenharmony_ci        }
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci        /* 32-bit alignment */
172cabdff1aSopenharmony_ci        avio_skip(pb, ((avio_tell(pb) + 3) & ~3) - avio_tell(pb));
173cabdff1aSopenharmony_ci    } else
174cabdff1aSopenharmony_ci        avio_seek(pb, 4, SEEK_SET);
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_ci    if (has_packet_info) {
177cabdff1aSopenharmony_ci        avpriv_request_sample(s, "RTP-X-QT with packet-specific info");
178cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
179cabdff1aSopenharmony_ci    }
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci    alen = len - avio_tell(pb);
182cabdff1aSopenharmony_ci    if (alen <= 0)
183cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
184cabdff1aSopenharmony_ci
185cabdff1aSopenharmony_ci    switch (packing_scheme) {
186cabdff1aSopenharmony_ci    case 3: /* one data packet spread over 1 or multiple RTP packets */
187cabdff1aSopenharmony_ci        if (qt->pkt->size > 0 && qt->timestamp == *timestamp) {
188cabdff1aSopenharmony_ci            int err;
189cabdff1aSopenharmony_ci            if ((err = av_reallocp(&qt->pkt->data, qt->pkt->size + alen +
190cabdff1aSopenharmony_ci                                   AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
191cabdff1aSopenharmony_ci                qt->pkt->size = 0;
192cabdff1aSopenharmony_ci                return err;
193cabdff1aSopenharmony_ci            }
194cabdff1aSopenharmony_ci        } else {
195cabdff1aSopenharmony_ci            av_freep(&qt->pkt->data);
196cabdff1aSopenharmony_ci            av_packet_unref(qt->pkt);
197cabdff1aSopenharmony_ci            qt->pkt->data = av_realloc(NULL, alen + AV_INPUT_BUFFER_PADDING_SIZE);
198cabdff1aSopenharmony_ci            if (!qt->pkt->data)
199cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
200cabdff1aSopenharmony_ci            qt->pkt->size = 0;
201cabdff1aSopenharmony_ci            qt->timestamp = *timestamp;
202cabdff1aSopenharmony_ci        }
203cabdff1aSopenharmony_ci        memcpy(qt->pkt->data + qt->pkt->size, buf + avio_tell(pb), alen);
204cabdff1aSopenharmony_ci        qt->pkt->size += alen;
205cabdff1aSopenharmony_ci        if (has_marker_bit) {
206cabdff1aSopenharmony_ci            int ret = av_packet_from_data(pkt, qt->pkt->data, qt->pkt->size);
207cabdff1aSopenharmony_ci            if (ret < 0)
208cabdff1aSopenharmony_ci                return ret;
209cabdff1aSopenharmony_ci
210cabdff1aSopenharmony_ci            qt->pkt->size = 0;
211cabdff1aSopenharmony_ci            qt->pkt->data = NULL;
212cabdff1aSopenharmony_ci            pkt->flags        = keyframe ? AV_PKT_FLAG_KEY : 0;
213cabdff1aSopenharmony_ci            pkt->stream_index = st->index;
214cabdff1aSopenharmony_ci            memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
215cabdff1aSopenharmony_ci            return 0;
216cabdff1aSopenharmony_ci        }
217cabdff1aSopenharmony_ci        return AVERROR(EAGAIN);
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci    case 1: /* constant packet size, multiple packets per RTP packet */
220cabdff1aSopenharmony_ci        if (qt->bytes_per_frame == 0 ||
221cabdff1aSopenharmony_ci            alen % qt->bytes_per_frame != 0)
222cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA; /* wrongly padded */
223cabdff1aSopenharmony_ci        qt->remaining = (alen / qt->bytes_per_frame) - 1;
224cabdff1aSopenharmony_ci        if ((ret = av_new_packet(pkt, qt->bytes_per_frame)) < 0)
225cabdff1aSopenharmony_ci            return ret;
226cabdff1aSopenharmony_ci        memcpy(pkt->data, buf + avio_tell(pb), qt->bytes_per_frame);
227cabdff1aSopenharmony_ci        pkt->flags = keyframe ? AV_PKT_FLAG_KEY : 0;
228cabdff1aSopenharmony_ci        pkt->stream_index = st->index;
229cabdff1aSopenharmony_ci        if (qt->remaining > 0) {
230cabdff1aSopenharmony_ci            av_freep(&qt->pkt->data);
231cabdff1aSopenharmony_ci            qt->pkt->data = av_realloc(NULL, qt->remaining * qt->bytes_per_frame);
232cabdff1aSopenharmony_ci            if (!qt->pkt->data) {
233cabdff1aSopenharmony_ci                av_packet_unref(pkt);
234cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
235cabdff1aSopenharmony_ci            }
236cabdff1aSopenharmony_ci            qt->pkt->size = qt->remaining * qt->bytes_per_frame;
237cabdff1aSopenharmony_ci            memcpy(qt->pkt->data,
238cabdff1aSopenharmony_ci                   buf + avio_tell(pb) + qt->bytes_per_frame,
239cabdff1aSopenharmony_ci                   qt->remaining * qt->bytes_per_frame);
240cabdff1aSopenharmony_ci            qt->pkt->flags = pkt->flags;
241cabdff1aSopenharmony_ci            return 1;
242cabdff1aSopenharmony_ci        }
243cabdff1aSopenharmony_ci        return 0;
244cabdff1aSopenharmony_ci
245cabdff1aSopenharmony_ci    default:  /* unimplemented */
246cabdff1aSopenharmony_ci        avpriv_request_sample(NULL, "RTP-X-QT with packing scheme 2");
247cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
248cabdff1aSopenharmony_ci    }
249cabdff1aSopenharmony_ci}
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_cistatic void qt_rtp_close(PayloadContext *qt)
252cabdff1aSopenharmony_ci{
253cabdff1aSopenharmony_ci    av_freep(&qt->pkt->data);
254cabdff1aSopenharmony_ci    av_packet_free(&qt->pkt);
255cabdff1aSopenharmony_ci}
256cabdff1aSopenharmony_ci
257cabdff1aSopenharmony_ci#define RTP_QT_HANDLER(m, n, s, t) \
258cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
259cabdff1aSopenharmony_ci    .enc_name         = s, \
260cabdff1aSopenharmony_ci    .codec_type       = t, \
261cabdff1aSopenharmony_ci    .codec_id         = AV_CODEC_ID_NONE, \
262cabdff1aSopenharmony_ci    .priv_data_size   = sizeof(PayloadContext), \
263cabdff1aSopenharmony_ci    .init             = qt_rtp_init,    \
264cabdff1aSopenharmony_ci    .close            = qt_rtp_close,   \
265cabdff1aSopenharmony_ci    .parse_packet     = qt_rtp_parse_packet, \
266cabdff1aSopenharmony_ci}
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_ciRTP_QT_HANDLER(qt,        vid, "X-QT",        AVMEDIA_TYPE_VIDEO);
269cabdff1aSopenharmony_ciRTP_QT_HANDLER(qt,        aud, "X-QT",        AVMEDIA_TYPE_AUDIO);
270cabdff1aSopenharmony_ciRTP_QT_HANDLER(quicktime, vid, "X-QUICKTIME", AVMEDIA_TYPE_VIDEO);
271cabdff1aSopenharmony_ciRTP_QT_HANDLER(quicktime, aud, "X-QUICKTIME", AVMEDIA_TYPE_AUDIO);
272