1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RTP MPEG2TS depacketizer
3cabdff1aSopenharmony_ci * Copyright (c) 2003 Fabrice Bellard
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 "libavutil/attributes.h"
23cabdff1aSopenharmony_ci#include "mpegts.h"
24cabdff1aSopenharmony_ci#include "rtpdec_formats.h"
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_cistruct PayloadContext {
27cabdff1aSopenharmony_ci    struct MpegTSContext *ts;
28cabdff1aSopenharmony_ci    int read_buf_index;
29cabdff1aSopenharmony_ci    int read_buf_size;
30cabdff1aSopenharmony_ci    uint8_t buf[RTP_MAX_PACKET_LENGTH];
31cabdff1aSopenharmony_ci};
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_cistatic void mpegts_close_context(PayloadContext *data)
34cabdff1aSopenharmony_ci{
35cabdff1aSopenharmony_ci    if (!data)
36cabdff1aSopenharmony_ci        return;
37cabdff1aSopenharmony_ci    if (data->ts)
38cabdff1aSopenharmony_ci        avpriv_mpegts_parse_close(data->ts);
39cabdff1aSopenharmony_ci}
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_cistatic av_cold int mpegts_init(AVFormatContext *ctx, int st_index,
42cabdff1aSopenharmony_ci                               PayloadContext *data)
43cabdff1aSopenharmony_ci{
44cabdff1aSopenharmony_ci    data->ts = avpriv_mpegts_parse_open(ctx);
45cabdff1aSopenharmony_ci    if (!data->ts)
46cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
47cabdff1aSopenharmony_ci    return 0;
48cabdff1aSopenharmony_ci}
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_cistatic int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data,
51cabdff1aSopenharmony_ci                                AVStream *st, AVPacket *pkt, uint32_t *timestamp,
52cabdff1aSopenharmony_ci                                const uint8_t *buf, int len, uint16_t seq,
53cabdff1aSopenharmony_ci                                int flags)
54cabdff1aSopenharmony_ci{
55cabdff1aSopenharmony_ci    int ret;
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_ci    // We don't want to use the RTP timestamps at all. If the mpegts demuxer
58cabdff1aSopenharmony_ci    // doesn't set any pts/dts, the generic rtpdec code shouldn't try to
59cabdff1aSopenharmony_ci    // fill it in either, since the mpegts and RTP timestamps are in totally
60cabdff1aSopenharmony_ci    // different ranges.
61cabdff1aSopenharmony_ci    *timestamp = RTP_NOTS_VALUE;
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_ci    if (!buf) {
64cabdff1aSopenharmony_ci        if (data->read_buf_index >= data->read_buf_size)
65cabdff1aSopenharmony_ci            return AVERROR(EAGAIN);
66cabdff1aSopenharmony_ci        ret = avpriv_mpegts_parse_packet(data->ts, pkt, data->buf + data->read_buf_index,
67cabdff1aSopenharmony_ci                                         data->read_buf_size - data->read_buf_index);
68cabdff1aSopenharmony_ci        if (ret < 0)
69cabdff1aSopenharmony_ci            return AVERROR(EAGAIN);
70cabdff1aSopenharmony_ci        data->read_buf_index += ret;
71cabdff1aSopenharmony_ci        if (data->read_buf_index < data->read_buf_size)
72cabdff1aSopenharmony_ci            return 1;
73cabdff1aSopenharmony_ci        else
74cabdff1aSopenharmony_ci            return 0;
75cabdff1aSopenharmony_ci    }
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ci    ret = avpriv_mpegts_parse_packet(data->ts, pkt, buf, len);
78cabdff1aSopenharmony_ci    /* The only error that can be returned from avpriv_mpegts_parse_packet
79cabdff1aSopenharmony_ci     * is "no more data to return from the provided buffer", so return
80cabdff1aSopenharmony_ci     * AVERROR(EAGAIN) for all errors */
81cabdff1aSopenharmony_ci    if (ret < 0)
82cabdff1aSopenharmony_ci        return AVERROR(EAGAIN);
83cabdff1aSopenharmony_ci    if (ret < len) {
84cabdff1aSopenharmony_ci        data->read_buf_size = FFMIN(len - ret, sizeof(data->buf));
85cabdff1aSopenharmony_ci        memcpy(data->buf, buf + ret, data->read_buf_size);
86cabdff1aSopenharmony_ci        data->read_buf_index = 0;
87cabdff1aSopenharmony_ci        return 1;
88cabdff1aSopenharmony_ci    }
89cabdff1aSopenharmony_ci    return 0;
90cabdff1aSopenharmony_ci}
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ciconst RTPDynamicProtocolHandler ff_mpegts_dynamic_handler = {
93cabdff1aSopenharmony_ci    .codec_type        = AVMEDIA_TYPE_DATA,
94cabdff1aSopenharmony_ci    .priv_data_size    = sizeof(PayloadContext),
95cabdff1aSopenharmony_ci    .parse_packet      = mpegts_handle_packet,
96cabdff1aSopenharmony_ci    .init              = mpegts_init,
97cabdff1aSopenharmony_ci    .close             = mpegts_close_context,
98cabdff1aSopenharmony_ci    .static_payload_id = 33,
99cabdff1aSopenharmony_ci};
100