Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/Makefile1
-rw-r--r--libavformat/rtpdec.c1
-rw-r--r--libavformat/rtpdec_formats.h1
-rw-r--r--libavformat/rtpdec_h263_rfc2190.c184
4 files changed, 187 insertions, 0 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile
index a465b2f44e..cacfaf8560 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -254,6 +254,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \
rtpdec_asf.o \
rtpdec_g726.o \
rtpdec_h263.o \
+ rtpdec_h263_rfc2190.o \
rtpdec_h264.o \
rtpdec_latm.o \
rtpdec_mpeg4.o \
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index 3442c9b2b1..668755ba41 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -66,6 +66,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
ff_register_dynamic_payload_handler(&ff_amr_wb_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h263_1998_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
+ ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 3074565db7..7f18ca4104 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -39,6 +39,7 @@ extern RTPDynamicProtocolHandler ff_g726_32_dynamic_handler;
extern RTPDynamicProtocolHandler ff_g726_40_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c
new file mode 100644
index 0000000000..baec6a427c
--- /dev/null
+++ b/libavformat/rtpdec_h263_rfc2190.c
@@ -0,0 +1,184 @@
+/*
+ * RTP H.263 Depacketizer, RFC 2190
+ * Copyright (c) 2012 Martin Storsjo
+ * Based on the GStreamer H.263 Depayloder:
+ * Copyright 2005 Wim Taymans
+ * Copyright 2007 Edward Hervey
+ * Copyright 2007 Nokia Corporation
+ * Copyright 2007 Collabora Ltd, Philippe Kalaf
+ * Copyright 2010 Mark Nauwelaerts
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "rtpdec_formats.h"
+#include "libavutil/intreadwrite.h"
+#include "libavcodec/get_bits.h"
+
+struct PayloadContext {
+ AVIOContext *buf;
+ uint8_t endbyte;
+ int endbyte_bits;
+ uint32_t timestamp;
+};
+
+static PayloadContext *h263_new_context(void)
+{
+ return av_mallocz(sizeof(PayloadContext));
+}
+
+static void h263_free_context(PayloadContext *data)
+{
+ if (!data)
+ return;
+ if (data->buf) {
+ uint8_t *p;
+ avio_close_dyn_buf(data->buf, &p);
+ av_free(p);
+ }
+ av_free(data);
+}
+
+static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data,
+ AVStream *st, AVPacket *pkt, uint32_t *timestamp,
+ const uint8_t *buf, int len, int flags)
+{
+ int f, p, i, sbit, ebit; /* Corresponding to header fields in the RFC */
+ int header_size;
+
+ if (data->buf && data->timestamp != *timestamp) {
+ /* Dropping old buffered, unfinished data */
+ uint8_t *p;
+ avio_close_dyn_buf(data->buf, &p);
+ av_free(p);
+ data->buf = NULL;
+ }
+
+ if (len < 4) {
+ av_log(ctx, AV_LOG_ERROR, "Too short H.263 RTP packet: %d\n", len);
+ return AVERROR_INVALIDDATA;
+ }
+
+ f = buf[0] & 0x80;
+ p = buf[0] & 0x40;
+ if (!f) {
+ /* Mode A */
+ header_size = 4;
+ i = buf[1] & 0x10;
+ } else if (!p) {
+ /* Mode B */
+ header_size = 8;
+ if (len < header_size) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Too short H.263 RTP packet: %d bytes, %d header bytes\n",
+ len, header_size);
+ return AVERROR_INVALIDDATA;
+ }
+ i = buf[4] & 0x80;
+ } else {
+ /* Mode C */
+ header_size = 12;
+ if (len < header_size) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Too short H.263 RTP packet: %d bytes, %d header bytes\n",
+ len, header_size);
+ return AVERROR_INVALIDDATA;
+ }
+ i = buf[4] & 0x80;
+ }
+ sbit = (buf[0] >> 3) & 0x7;
+ ebit = buf[0] & 0x7;
+
+ buf += header_size;
+ len -= header_size;
+
+ if (!data->buf) {
+ /* Check the picture start code, only start buffering a new frame
+ * if this is correct */
+ if (!f && len > 4 && AV_RB32(buf) >> 10 == 0x20) {
+ int ret = avio_open_dyn_buf(&data->buf);
+ if (ret < 0)
+ return ret;
+ data->timestamp = *timestamp;
+ } else {
+ /* Frame not started yet, skipping */
+ return AVERROR(EAGAIN);
+ }
+ }
+
+ if (data->endbyte_bits || sbit) {
+ if (data->endbyte_bits == sbit) {
+ data->endbyte |= buf[0] & (0xff >> sbit);
+ data->endbyte_bits = 0;
+ buf++;
+ len--;
+ avio_w8(data->buf, data->endbyte);
+ } else {
+ /* Start/end skip bits not matching - missed packets? */
+ GetBitContext gb;
+ init_get_bits(&gb, buf, len*8 - ebit);
+ skip_bits(&gb, sbit);
+ if (data->endbyte_bits) {
+ data->endbyte |= get_bits(&gb, 8 - data->endbyte_bits);
+ avio_w8(data->buf, data->endbyte);
+ }
+ while (get_bits_left(&gb) >= 8)
+ avio_w8(data->buf, get_bits(&gb, 8));
+ data->endbyte_bits = get_bits_left(&gb);
+ if (data->endbyte_bits)
+ data->endbyte = get_bits(&gb, data->endbyte_bits) <<
+ (8 - data->endbyte_bits);
+ ebit = 0;
+ len = 0;
+ }
+ }
+ if (ebit) {
+ if (len > 0)
+ avio_write(data->buf, buf, len - 1);
+ data->endbyte_bits = 8 - ebit;
+ data->endbyte = buf[len - 1] & (0xff << ebit);
+ } else {
+ avio_write(data->buf, buf, len);
+ }
+
+ if (!(flags & RTP_FLAG_MARKER))
+ return AVERROR(EAGAIN);
+
+ if (data->endbyte_bits)
+ avio_w8(data->buf, data->endbyte);
+ data->endbyte_bits = 0;
+
+ av_init_packet(pkt);
+ pkt->size = avio_close_dyn_buf(data->buf, &pkt->data);
+ pkt->destruct = av_destruct_packet;
+ pkt->stream_index = st->index;
+ if (!i)
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ data->buf = NULL;
+
+ return 0;
+}
+
+RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler = {
+ .codec_type = AVMEDIA_TYPE_VIDEO,
+ .codec_id = CODEC_ID_H263,
+ .parse_packet = h263_handle_packet,
+ .alloc = h263_new_context,
+ .free = h263_free_context,
+ .static_payload_id = 34,
+};