[FFmpeg-devel] H.261 and H.263 RTP broken?
Alexandre FERRIEUX - FT/RD/SIRP/ASF/SOFTL
alexandre.ferrieux
Thu Jan 29 09:22:01 CET 2009
Luca Abeni wrote:
> Georges-Etienne Legendre wrote:
>> Is there someone who works on RTP H.263 decoding? This patch only does
>> the encoding part.
>
> If you look at the ml archives, you'll see that there is someone working
> on receiving H.263 over RTP. But I did not see any patch yet, so I do not
> know what's the status.
>
> I heard of other people working on H.263 over RTP in the past, but noone
> ever posted a patch (AFAIK).
>
>
> Luca
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at mplayerhq.hu
> https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel
>
(I sent this already with attached files, but the bouncer seems to block
them silently. Retrying with the code in-line.)
OK here is my little contribution. With this I correctly receive
H263/RTP streams from a mobile phone. Forgive the naive style and
overall bad quality, I'm a beginner with ffmpeg internals and I really
thought somebody more knowledgeable would take over :-}
Notice that the following hunk in rtpdec.c:
+ //Alex
+ // now perform timestamp things....
+ finalize_packet(s, pkt, timestamp);
is a somewhat "random shot in the dark" suggested by one remark by Luca
about the contracts at this spot, making me think the finalize_packet(0
call was just missing here. Take this with a grain of salt and shoot on
first hint of a problem...
-Alex
(in-line pasting 3 files: h263.patch for existsing files, and
rtp_h263.[ch] which are new. I don't know the svn equivalent of "cvs
diff -N" to include new files)
------ File h263.patch ---------------------------
Index: libavformat/rtpdec.c
===================================================================
--- libavformat/rtpdec.c (revision 16849)
+++ libavformat/rtpdec.c (working copy)
@@ -31,6 +31,7 @@
#include "rtp.h"
#include "rtp_h264.h"
+#include "rtp_h263.h"
//#define DEBUG
@@ -60,6 +61,7 @@
ff_register_dynamic_payload_handler(&mp4v_es_handler);
ff_register_dynamic_payload_handler(&mpeg4_generic_handler);
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+ ff_register_dynamic_payload_handler(&ff_h263_dynamic_handler);
}
static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char
*buf, int len)
@@ -296,6 +298,8 @@
case CODEC_ID_MP3:
case CODEC_ID_MPEG4:
case CODEC_ID_H264:
+ case CODEC_ID_H263:
+ case CODEC_ID_H263P:
st->need_parsing = AVSTREAM_PARSE_FULL;
break;
default:
@@ -437,6 +441,7 @@
return -1;
}
payload_type = buf[1] & 0x7f;
+ if (buf[1] & 0x80) flags |= RTP_FLAG_M_BIT;
seq = AV_RB16(buf + 2);
timestamp = AV_RB32(buf + 4);
ssrc = AV_RB32(buf + 8);
@@ -474,7 +479,10 @@
} else if (s->parse_packet) {
rv = s->parse_packet(s->dynamic_protocol_context,
s->st, pkt, ×tamp, buf, len, flags);
+ //Alex
+ // now perform timestamp things....
+ finalize_packet(s, pkt, timestamp);
} else {
// at this point, the RTP header has been stripped; This is
ASSUMING that there is only 1 CSRC, which in't wise.
switch(st->codec->codec_id) {
Index: libavformat/Makefile
===================================================================
--- libavformat/Makefile (revision 16849)
+++ libavformat/Makefile (working copy)
@@ -166,7 +166,7 @@
rtpenc_h264.o \
avc.o
OBJS-$(CONFIG_RTSP_DEMUXER) += rdt.o rtsp.o
-OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o rtp.o rtpdec.o
rtp_h264.o
+OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o rtp.o rtpdec.o
rtp_h264.o rtp_h263.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o
OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o
------- File rtp_h263.c ---------------------------------------------
/*
* RTP H263/H263+ Protocol (RFC2429)
* Copyright (c) 2009 Alexandre Ferrieux
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/**
* @file rtp_h263.c
* @brief H.263/H.263+ / RTP Code (RFC2429)
* @author Alexandre Ferrieux <alexandre.ferrieux at orange-ftgroup.com>
*
* @note Notes:
* Notes:
* This currently supports only the non-error-resilient packetization mode:
* (see last paragraph of RFC2429, section 6)
*
*/
#include "libavutil/base64.h"
#include "libavutil/avstring.h"
#include "libavcodec/bitstream.h"
#include "avformat.h"
#include "mpegts.h"
#include <unistd.h>
#include "network.h"
#include <assert.h>
#include "rtp_internal.h"
#include "rtp_h263.h"
#define BIGBUF 1000000 /* upper bound of picture size */
/**
RTP/H263 specific private data.
*/
struct PayloadContext {
unsigned long cookie; ///< sanity check, to make sure we get
the pointer we're expecting.
char buf[BIGBUF];
int pos;
};
#define MAGIC_COOKIE (0xdeadbeef) ///< Cookie for the extradata;
to verify we are what we think we are, and that we haven't been freed.
#define DEAD_COOKIE (0xdeaddead) ///< Cookie for the extradata;
once it is freed.
/* ---------------- private code */
static void sdp_parse_fmtp_config_h263(AVStream * stream,
PayloadContext * h263_data,
char *attr, char *value)
{
AVCodecContext *codec = stream->codec;
assert(codec->codec_id == CODEC_ID_H263);
assert(h263_data != NULL);
/* nothing */
}
// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
static int bad_h263_handle_packet(PayloadContext *data,
AVStream *st,
AVPacket * pkt,
uint32_t * timestamp,
const uint8_t * buf,
int len, int flags)
{
#ifdef DEBUG
assert(data);
assert(data->cookie == MAGIC_COOKIE);
#endif
assert(buf);
if(buf[0] & 0x04) /* P bit in H263 payload header */
{
data->buf[0]=0;
data->buf[1]=0;
memcpy(data->buf+2, buf+2, len-2);
data->pos=len;
}
else
{
memcpy(data->buf+data->pos,buf+2,len-2);
data->pos+=(len-2);
}
if (flags&RTP_FLAG_M_BIT) /* M bit in RTP header */
{
av_new_packet(pkt,data->pos);
memcpy(pkt->data,data->buf,data->pos);
data->pos=0;
return 0;
}
return -1;
}
// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
static int h263_handle_packet(PayloadContext *data,
AVStream *st,
AVPacket * pkt,
uint32_t * timestamp,
const uint8_t * buf,
int len, int flags)
{
static int dumph263=-1;
if (dumph263<0)
{
char *dumph263val=getenv("FFMPEG_DUMPH263");
dumph263=(dumph263val && (0==strcmp(dumph263val,"1")));
}
#ifdef DEBUG
assert(data);
assert(data->cookie == MAGIC_COOKIE);
#endif
assert(buf);
if(buf[0] & 0x04) /* P bit */
{
av_new_packet(pkt, len);
/* restore 0000 encoded by P */
pkt->data[0]=0;
pkt->data[1]=0;
memcpy(pkt->data+2, buf+2, len-2);
}
else
{
av_new_packet(pkt, len-2);
memcpy(pkt->data, buf+2, len-2);
}
if (dumph263) fwrite(pkt->data,1,pkt->size,stdout);
return 0;
}
/* ---------------- public code */
static PayloadContext *h263_new_extradata(void)
{
PayloadContext *data =
av_mallocz(sizeof(PayloadContext));
if (data) {
data->cookie = MAGIC_COOKIE;
}
return data;
}
static void h263_free_extradata(PayloadContext *data)
{
assert(data);
assert(data->cookie == MAGIC_COOKIE);
// avoid stale pointers (assert)
data->cookie = DEAD_COOKIE;
// and clear out this...
av_free(data);
}
static int parse_h263_sdp_line(AVFormatContext *s, int st_index,
PayloadContext *h263_data, const char *line)
{
AVStream *stream = s->streams[st_index];
av_set_pts_info(stream, 33, 1, 90000); // 33 should be right,
because the pts is 64 bit? (done elsewhere; this is a one time thing)
return 0; // keep processing it the normal way...
}
/**
This is the structure for expanding on the dynamic rtp protocols (makes
everything static. yay!)
*/
RTPDynamicProtocolHandler ff_h263_dynamic_handler = {
"H263",
CODEC_TYPE_VIDEO,
CODEC_ID_H263,
parse_h263_sdp_line,
h263_new_extradata,
h263_free_extradata,
h263_handle_packet
};
---------- File rtp_h263.h ----------------
/*
* RTP H263/H263+ Protocol (RFC2429)
* Copyright (c) 2009 Alexandre Ferrieux
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#ifndef AVFORMAT_RTP_H263_H
#define AVFORMAT_RTP_H263_H
#include "rtp_internal.h"
extern RTPDynamicProtocolHandler ff_h263_dynamic_handler;
void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size);
#endif /* AVFORMAT_RTP_H263_H */
More information about the ffmpeg-devel
mailing list