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