[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, &timestamp, 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