* qatar/master: rtp: Packetization of JPEG (RFC 2435) smoothstreamingenc: Copy the SAR on the AVStreams as well Conflicts: Changelog libavformat/rtpenc.c libavformat/version.h Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.0
@@ -64,6 +64,7 @@ version next: | |||||
- F4V muxer | - F4V muxer | ||||
- sendcmd and asendcmd filters | - sendcmd and asendcmd filters | ||||
- WebVTT demuxer and decoder (simple tags supported) | - WebVTT demuxer and decoder (simple tags supported) | ||||
- RTP packetization of JPEG | |||||
version 0.11: | version 0.11: | ||||
@@ -277,6 +277,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ | |||||
rtpenc_amr.o \ | rtpenc_amr.o \ | ||||
rtpenc_h263.o \ | rtpenc_h263.o \ | ||||
rtpenc_h263_rfc2190.o \ | rtpenc_h263_rfc2190.o \ | ||||
rtpenc_jpeg.o \ | |||||
rtpenc_mpv.o \ | rtpenc_mpv.o \ | ||||
rtpenc.o \ | rtpenc.o \ | ||||
rtpenc_h264.o \ | rtpenc_h264.o \ | ||||
@@ -76,6 +76,7 @@ static int is_supported(enum AVCodecID id) | |||||
case AV_CODEC_ID_ADPCM_G726: | case AV_CODEC_ID_ADPCM_G726: | ||||
case AV_CODEC_ID_ILBC: | case AV_CODEC_ID_ILBC: | ||||
case AV_CODEC_ID_SPEEX: | case AV_CODEC_ID_SPEEX: | ||||
case AV_CODEC_ID_MJPEG: | |||||
return 1; | return 1; | ||||
default: | default: | ||||
return 0; | return 0; | ||||
@@ -525,6 +526,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) | |||||
case AV_CODEC_ID_ILBC: | case AV_CODEC_ID_ILBC: | ||||
rtp_send_ilbc(s1, pkt->data, size); | rtp_send_ilbc(s1, pkt->data, size); | ||||
break; | break; | ||||
case AV_CODEC_ID_MJPEG: | |||||
ff_rtp_send_jpeg(s1, pkt->data, size); | |||||
break; | |||||
default: | default: | ||||
/* better than nothing : send the codec raw data */ | /* better than nothing : send the codec raw data */ | ||||
rtp_send_raw(s1, pkt->data, size); | rtp_send_raw(s1, pkt->data, size); | ||||
@@ -87,6 +87,7 @@ void ff_rtp_send_amr(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); | ||||
void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size); | void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size); | ||||
void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); | void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); | ||||
void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size); | |||||
const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start, | const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start, | ||||
const uint8_t *av_restrict end); | const uint8_t *av_restrict end); | ||||
@@ -0,0 +1,138 @@ | |||||
/* | |||||
* RTP JPEG-compressed video Packetizer, RFC 2435 | |||||
* Copyright (c) 2012 Samuel Pitoiset | |||||
* | |||||
* 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 "libavcodec/bytestream.h" | |||||
#include "libavcodec/mjpeg.h" | |||||
#include "libavutil/intreadwrite.h" | |||||
#include "rtpenc.h" | |||||
void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) | |||||
{ | |||||
RTPMuxContext *s = s1->priv_data; | |||||
const uint8_t *qtables = NULL; | |||||
int nb_qtables = 0; | |||||
uint8_t type = 1; /* default pixel format is PIX_FMT_YUVJ420P */ | |||||
uint8_t w, h; | |||||
uint8_t *p; | |||||
int off = 0; /* fragment offset of the current JPEG frame */ | |||||
int len; | |||||
int i; | |||||
s->buf_ptr = s->buf; | |||||
s->timestamp = s->cur_timestamp; | |||||
/* convert video pixel dimensions from pixels to blocks */ | |||||
w = s1->streams[0]->codec->width >> 3; | |||||
h = s1->streams[0]->codec->height >> 3; | |||||
/* check if pixel format is not the normal 420 case */ | |||||
if (s1->streams[0]->codec->pix_fmt == PIX_FMT_YUVJ422P) { | |||||
type = 0; | |||||
} else if (s1->streams[0]->codec->pix_fmt == PIX_FMT_YUVJ420P) { | |||||
type = 1; | |||||
} else { | |||||
av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n"); | |||||
return; | |||||
} | |||||
/* preparse the header for getting some infos */ | |||||
for (i = 0; i < size; i++) { | |||||
if (buf[i] != 0xff) | |||||
continue; | |||||
if (buf[i + 1] == DQT) { | |||||
if (buf[i + 4]) | |||||
av_log(s1, AV_LOG_WARNING, | |||||
"Only 8-bit precision is supported.\n"); | |||||
/* a quantization table is 64 bytes long */ | |||||
nb_qtables = AV_RB16(&buf[i + 2]) / 65; | |||||
if (i + 4 + nb_qtables * 65 > size) { | |||||
av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n"); | |||||
return; | |||||
} | |||||
qtables = &buf[i + 4]; | |||||
} else if (buf[i + 1] == SOF0) { | |||||
if (buf[i + 14] != 17 || buf[i + 17] != 17) { | |||||
av_log(s1, AV_LOG_ERROR, | |||||
"Only 1x1 chroma blocks are supported. Aborted!\n"); | |||||
return; | |||||
} | |||||
} else if (buf[i + 1] == SOS) { | |||||
/* SOS is last marker in the header */ | |||||
i += AV_RB16(&buf[i + 2]) + 2; | |||||
break; | |||||
} | |||||
} | |||||
/* skip JPEG header */ | |||||
buf += i; | |||||
size -= i; | |||||
for (i = size - 2; i >= 0; i--) { | |||||
if (buf[i] == 0xff && buf[i + 1] == EOI) { | |||||
/* Remove the EOI marker */ | |||||
size = i; | |||||
break; | |||||
} | |||||
} | |||||
p = s->buf_ptr; | |||||
while (size > 0) { | |||||
int hdr_size = 8; | |||||
if (off == 0 && nb_qtables) | |||||
hdr_size += 4 + 64 * nb_qtables; | |||||
/* payload max in one packet */ | |||||
len = FFMIN(size, s->max_payload_size - hdr_size); | |||||
/* set main header */ | |||||
bytestream_put_byte(&p, 0); | |||||
bytestream_put_be24(&p, off); | |||||
bytestream_put_byte(&p, type); | |||||
bytestream_put_byte(&p, 255); | |||||
bytestream_put_byte(&p, w); | |||||
bytestream_put_byte(&p, h); | |||||
if (off == 0 && nb_qtables) { | |||||
/* set quantization tables header */ | |||||
bytestream_put_byte(&p, 0); | |||||
bytestream_put_byte(&p, 0); | |||||
bytestream_put_be16(&p, 64 * nb_qtables); | |||||
for (i = 0; i < nb_qtables; i++) | |||||
bytestream_put_buffer(&p, &qtables[65 * i + 1], 64); | |||||
} | |||||
/* copy payload data */ | |||||
memcpy(p, buf, len); | |||||
/* marker bit is last packet in frame */ | |||||
ff_rtp_send_data(s1, s->buf, len + hdr_size, size == len); | |||||
buf += len; | |||||
size -= len; | |||||
off += len; | |||||
p = s->buf; | |||||
} | |||||
} |
@@ -547,6 +547,11 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, | |||||
av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", | av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", | ||||
payload_type); | payload_type); | ||||
break; | break; | ||||
case AV_CODEC_ID_MJPEG: | |||||
if (payload_type >= RTP_PT_PRIVATE) | |||||
av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", | |||||
payload_type); | |||||
break; | |||||
case AV_CODEC_ID_ADPCM_G722: | case AV_CODEC_ID_ADPCM_G722: | ||||
if (payload_type >= RTP_PT_PRIVATE) | if (payload_type >= RTP_PT_PRIVATE) | ||||
av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", | av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", | ||||
@@ -239,6 +239,7 @@ static int ism_write_header(AVFormatContext *s) | |||||
goto fail; | goto fail; | ||||
} | } | ||||
avcodec_copy_context(st->codec, s->streams[i]->codec); | avcodec_copy_context(st->codec, s->streams[i]->codec); | ||||
st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; | |||||
ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); | ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); | ||||
if (!ctx->pb) { | if (!ctx->pb) { | ||||
@@ -31,7 +31,7 @@ | |||||
#define LIBAVFORMAT_VERSION_MAJOR 54 | #define LIBAVFORMAT_VERSION_MAJOR 54 | ||||
#define LIBAVFORMAT_VERSION_MINOR 28 | #define LIBAVFORMAT_VERSION_MINOR 28 | ||||
#define LIBAVFORMAT_VERSION_MICRO 100 | |||||
#define LIBAVFORMAT_VERSION_MICRO 101 | |||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||
LIBAVFORMAT_VERSION_MINOR, \ | LIBAVFORMAT_VERSION_MINOR, \ | ||||