patch by Martin Storsjö (martin AT martin DOT st) Originally committed as revision 18347 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.6
| @@ -6,6 +6,7 @@ version <next>: | |||||
| - VQF demuxer | - VQF demuxer | ||||
| - Alpha channel scaler | - Alpha channel scaler | ||||
| - PCX encoder | - PCX encoder | ||||
| - RTP packetization of H.263 | |||||
| @@ -189,6 +189,7 @@ OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o | |||||
| OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ | OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ | ||||
| rtp_aac.o \ | rtp_aac.o \ | ||||
| rtp_asf.o \ | rtp_asf.o \ | ||||
| rtp_h263.o \ | |||||
| rtp_mpv.o \ | rtp_mpv.o \ | ||||
| rtpenc.o \ | rtpenc.o \ | ||||
| rtpenc_h264.o \ | rtpenc_h264.o \ | ||||
| @@ -0,0 +1,80 @@ | |||||
| /* | |||||
| * RTP packetization for H.263 video | |||||
| * Copyright (c) 2009 Luca Abeni | |||||
| * Copyright (c) 2007 Martin Storsjo | |||||
| * | |||||
| * 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 | |||||
| */ | |||||
| #include "avformat.h" | |||||
| #include "rtpenc.h" | |||||
| static const uint8_t *find_resync_marker_reverse(const uint8_t *restrict start, | |||||
| const uint8_t *restrict end) | |||||
| { | |||||
| const uint8_t *p = end - 1; | |||||
| start += 1; /* Make sure we never return the original start. */ | |||||
| for (; p > start; p -= 2) { | |||||
| if (!*p) { | |||||
| if (!p[ 1] && p[2]) return p; | |||||
| else if (!p[-1] && p[1]) return p - 1; | |||||
| } | |||||
| } | |||||
| return end; | |||||
| } | |||||
| /** | |||||
| * Packetize H.263 frames into RTP packets according to RFC 4629 | |||||
| */ | |||||
| void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size) | |||||
| { | |||||
| RTPMuxContext *s = s1->priv_data; | |||||
| int len, max_packet_size; | |||||
| uint8_t *q; | |||||
| max_packet_size = s->max_payload_size; | |||||
| while (size > 0) { | |||||
| q = s->buf; | |||||
| if ((buf1[0] == 0) && (buf1[1] == 0)) { | |||||
| *q++ = 0x04; | |||||
| buf1 += 2; | |||||
| size -= 2; | |||||
| } else { | |||||
| *q++ = 0; | |||||
| } | |||||
| *q++ = 0; | |||||
| len = FFMIN(max_packet_size - 2, size); | |||||
| /* Look for a better place to split the frame into packets. */ | |||||
| if (len < size) { | |||||
| const uint8_t *end = find_resync_marker_reverse(buf1, buf1 + len); | |||||
| len = end - buf1; | |||||
| } | |||||
| memcpy(q, buf1, len); | |||||
| q += len; | |||||
| /* 90 KHz time stamp */ | |||||
| s->timestamp = s->cur_timestamp; | |||||
| ff_rtp_send_data(s1, s->buf, q - s->buf, (len == size)); | |||||
| buf1 += len; | |||||
| size -= len; | |||||
| } | |||||
| } | |||||
| @@ -42,6 +42,8 @@ static uint64_t ntp_time(void) | |||||
| static int is_supported(enum CodecID id) | static int is_supported(enum CodecID id) | ||||
| { | { | ||||
| switch(id) { | switch(id) { | ||||
| case CODEC_ID_H263: | |||||
| case CODEC_ID_H263P: | |||||
| case CODEC_ID_H264: | case CODEC_ID_H264: | ||||
| case CODEC_ID_MPEG1VIDEO: | case CODEC_ID_MPEG1VIDEO: | ||||
| case CODEC_ID_MPEG2VIDEO: | case CODEC_ID_MPEG2VIDEO: | ||||
| @@ -370,6 +372,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) | |||||
| case CODEC_ID_H264: | case CODEC_ID_H264: | ||||
| ff_rtp_send_h264(s1, buf1, size); | ff_rtp_send_h264(s1, buf1, size); | ||||
| break; | break; | ||||
| case CODEC_ID_H263: | |||||
| case CODEC_ID_H263P: | |||||
| ff_rtp_send_h263(s1, buf1, size); | |||||
| break; | |||||
| default: | default: | ||||
| /* better than nothing : send the codec raw data */ | /* better than nothing : send the codec raw data */ | ||||
| rtp_send_raw(s1, buf1, size); | rtp_send_raw(s1, buf1, size); | ||||
| @@ -57,6 +57,7 @@ typedef struct RTPMuxContext RTPMuxContext; | |||||
| void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); | void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m); | ||||
| void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); | void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size); | ||||
| void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size); | |||||
| void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size); | void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size); | ||||
| void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size); | void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size); | ||||
| @@ -177,6 +177,10 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, | |||||
| payload_type, | payload_type, | ||||
| payload_type, config ? config : ""); | payload_type, config ? config : ""); | ||||
| break; | break; | ||||
| case CODEC_ID_H263: | |||||
| case CODEC_ID_H263P: | |||||
| av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n", payload_type); | |||||
| break; | |||||
| case CODEC_ID_MPEG4: | case CODEC_ID_MPEG4: | ||||
| if (c->extradata_size) { | if (c->extradata_size) { | ||||
| config = extradata2config(c); | config = extradata2config(c); | ||||