* qatar/master: mingw/cygwin: Stop adding -fno-common to gcc CFLAGS Restructure av_log_missing_feature message rtp: Support packetization/depacketization of opus file: Set the return value type for lseek to int64_t. ppc: fix Altivec build with old compilers build: add LTO support for PGI compiler build: add -Mdse to PGI optimisation flags rtpenc_vp8: Update the packetizer to the latest spec version rtpdec_vp8: Make the depacketizer implement the latest spec draft doc: allow building with old texi2html versions avutil: skip old_pix_fmts.h since it is just a list Conflicts: libavcodec/aacdec.c libavcodec/h264.c libavcodec/ppc/fmtconvert_altivec.c libavcodec/utils.c libavformat/file.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.1
| @@ -2429,6 +2429,7 @@ msvc_flags(){ | |||||
| pgi_flags(){ | pgi_flags(){ | ||||
| for flag; do | for flag; do | ||||
| case $flag in | case $flag in | ||||
| -flto) echo -Mipa=fast,libopt,libinline,vestigial ;; | |||||
| -fomit-frame-pointer) echo -Mnoframe ;; | -fomit-frame-pointer) echo -Mnoframe ;; | ||||
| -g) echo -gopt ;; | -g) echo -gopt ;; | ||||
| *) echo $flag ;; | *) echo $flag ;; | ||||
| @@ -2607,7 +2608,7 @@ probe_cc(){ | |||||
| elif $_cc -V 2>&1 | grep -q Portland; then | elif $_cc -V 2>&1 | grep -q Portland; then | ||||
| _type=pgi | _type=pgi | ||||
| _ident="PGI $($_cc -V 2>&1 | awk '/^pgcc/ { print $2; exit }')" | _ident="PGI $($_cc -V 2>&1 | awk '/^pgcc/ { print $2; exit }')" | ||||
| opt_common='-alias=ansi -Mlre -Mpre' | |||||
| opt_common='-alias=ansi -Mdse -Mlre -Mpre' | |||||
| _cflags_speed="-O3 -Mautoinline -Munroll=c:4 $opt_common" | _cflags_speed="-O3 -Mautoinline -Munroll=c:4 $opt_common" | ||||
| _cflags_size="-O2 -Munroll=c:1 $opt_common" | _cflags_size="-O2 -Munroll=c:1 $opt_common" | ||||
| _cflags_noopt="-O1" | _cflags_noopt="-O1" | ||||
| @@ -3109,7 +3110,6 @@ case $target_os in | |||||
| objformat="win32" | objformat="win32" | ||||
| ranlib=: | ranlib=: | ||||
| enable dos_paths | enable dos_paths | ||||
| check_cflags -fno-common | |||||
| add_cppflags -U__STRICT_ANSI__ | add_cppflags -U__STRICT_ANSI__ | ||||
| ;; | ;; | ||||
| cygwin*) | cygwin*) | ||||
| @@ -3125,7 +3125,6 @@ case $target_os in | |||||
| SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(FULLNAME).dll.a' | SHFLAGS='-shared -Wl,--out-implib,$(SUBDIR)lib$(FULLNAME).dll.a' | ||||
| objformat="win32" | objformat="win32" | ||||
| enable dos_paths | enable dos_paths | ||||
| check_cflags -fno-common | |||||
| add_cppflags -U__STRICT_ANSI__ | add_cppflags -U__STRICT_ANSI__ | ||||
| ;; | ;; | ||||
| *-dos|freedos|opendos) | *-dos|freedos|opendos) | ||||
| @@ -145,7 +145,8 @@ $print_page_foot = \&FFmpeg_print_page_foot; | |||||
| sub FFmpeg_print_page_foot($$) | sub FFmpeg_print_page_foot($$) | ||||
| { | { | ||||
| my $fh = shift; | my $fh = shift; | ||||
| my $program_string = T2H_DEFAULT_program_string(); | |||||
| my $program_string = defined &T2H_DEFAULT_program_string ? | |||||
| T2H_DEFAULT_program_string() : program_string(); | |||||
| print $fh '<footer class="footer pagination-right">' . "\n"; | print $fh '<footer class="footer pagination-right">' . "\n"; | ||||
| print $fh '<span class="label label-info">' . $program_string; | print $fh '<span class="label label-info">' . $program_string; | ||||
| print $fh "</span></footer></div>\n"; | print $fh "</span></footer></div>\n"; | ||||
| @@ -61,7 +61,7 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, | |||||
| } | } | ||||
| if (!hdr.crc_absent && hdr.num_aac_frames > 1) { | if (!hdr.crc_absent && hdr.num_aac_frames > 1) { | ||||
| av_log_missing_feature(avctx, "Multiple RDBs per frame with CRC is", 0); | |||||
| av_log_missing_feature(avctx, "Multiple RDBs per frame with CRC", 0); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -74,7 +74,7 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc, | |||||
| if (!hdr.chan_config) { | if (!hdr.chan_config) { | ||||
| init_get_bits(&gb, buf, buf_size * 8); | init_get_bits(&gb, buf, buf_size * 8); | ||||
| if (get_bits(&gb, 3) != 5) { | if (get_bits(&gb, 3) != 5) { | ||||
| av_log_missing_feature(avctx, "PCE based channel configuration, where the PCE is not the first syntax element is", 0); | |||||
| av_log_missing_feature(avctx, "PCE based channel configuration, where the PCE is not the first syntax element", 0); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| init_put_bits(&pb, pce_data, MAX_PCE_SIZE); | init_put_bits(&pb, pce_data, MAX_PCE_SIZE); | ||||
| @@ -665,7 +665,7 @@ static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx, | |||||
| int tags = 0; | int tags = 0; | ||||
| if (get_bits1(gb)) { // frameLengthFlag | if (get_bits1(gb)) { // frameLengthFlag | ||||
| av_log_missing_feature(avctx, "960/120 MDCT window is", 1); | |||||
| av_log_missing_feature(avctx, "960/120 MDCT window", 1); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -2388,7 +2388,7 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) | |||||
| if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { | if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { | ||||
| // This is 2 for "VLB " audio in NSV files. | // This is 2 for "VLB " audio in NSV files. | ||||
| // See samples/nsv/vlb_audio. | // See samples/nsv/vlb_audio. | ||||
| av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0); | |||||
| av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame", 0); | |||||
| ac->warned_num_aac_frames = 1; | ac->warned_num_aac_frames = 1; | ||||
| } | } | ||||
| push_output_configuration(ac); | push_output_configuration(ac); | ||||
| @@ -2728,8 +2728,8 @@ static int latm_decode_audio_specific_config(struct LATMContext *latmctx, | |||||
| asclen = get_bits_left(gb); | asclen = get_bits_left(gb); | ||||
| if (config_start_bit % 8) { | if (config_start_bit % 8) { | ||||
| av_log_missing_feature(latmctx->aac_ctx.avctx, "audio specific " | |||||
| "config not byte aligned.\n", 1); | |||||
| av_log_missing_feature(latmctx->aac_ctx.avctx, | |||||
| "Non-byte-aligned audio-specific config", 1); | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| if (asclen <= 0) | if (asclen <= 0) | ||||
| @@ -2789,7 +2789,7 @@ static int read_stream_mux_config(struct LATMContext *latmctx, | |||||
| // numPrograms | // numPrograms | ||||
| if (get_bits(gb, 4)) { // numPrograms | if (get_bits(gb, 4)) { // numPrograms | ||||
| av_log_missing_feature(latmctx->aac_ctx.avctx, | av_log_missing_feature(latmctx->aac_ctx.avctx, | ||||
| "multiple programs are not supported\n", 1); | |||||
| "multiple programs", 1); | |||||
| return AVERROR_PATCHWELCOME; | return AVERROR_PATCHWELCOME; | ||||
| } | } | ||||
| @@ -2798,7 +2798,7 @@ static int read_stream_mux_config(struct LATMContext *latmctx, | |||||
| // for each layer (which there is only one in DVB) | // for each layer (which there is only one in DVB) | ||||
| if (get_bits(gb, 3)) { // numLayer | if (get_bits(gb, 3)) { // numLayer | ||||
| av_log_missing_feature(latmctx->aac_ctx.avctx, | av_log_missing_feature(latmctx->aac_ctx.avctx, | ||||
| "multiple layers are not supported\n", 1); | |||||
| "multiple layers", 1); | |||||
| return AVERROR_PATCHWELCOME; | return AVERROR_PATCHWELCOME; | ||||
| } | } | ||||
| @@ -1077,7 +1077,7 @@ static int decode_seq_header(AVSContext *h) { | |||||
| width = get_bits(&s->gb, 14); | width = get_bits(&s->gb, 14); | ||||
| height = get_bits(&s->gb, 14); | height = get_bits(&s->gb, 14); | ||||
| if ((s->width || s->height) && (s->width != width || s->height != height)) { | if ((s->width || s->height) && (s->width != width || s->height != height)) { | ||||
| av_log_missing_feature(s, "Width/height changing in CAVS is", 0); | |||||
| av_log_missing_feature(s, "Width/height changing in CAVS", 0); | |||||
| return AVERROR_PATCHWELCOME; | return AVERROR_PATCHWELCOME; | ||||
| } | } | ||||
| if (width <= 0 || height <= 0) { | if (width <= 0 || height <= 0) { | ||||
| @@ -2451,7 +2451,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0) | |||||
| if(must_reinit && (h != h0 || (s->avctx->active_thread_type & FF_THREAD_FRAME))) { | if(must_reinit && (h != h0 || (s->avctx->active_thread_type & FF_THREAD_FRAME))) { | ||||
| av_log_missing_feature(s->avctx, | av_log_missing_feature(s->avctx, | ||||
| "Width/height/bit depth/chroma idc changing with threads is", 0); | |||||
| "Width/height/bit depth/chroma idc changing with threads", 0); | |||||
| return AVERROR_PATCHWELCOME; // width / height changed during parallelized decoding | return AVERROR_PATCHWELCOME; // width / height changed during parallelized decoding | ||||
| } | } | ||||
| @@ -256,8 +256,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) | |||||
| } | } | ||||
| if (s->ls && !(s->bits <= 8 || nb_components == 1)) { | if (s->ls && !(s->bits <= 8 || nb_components == 1)) { | ||||
| av_log_missing_feature(s->avctx, | av_log_missing_feature(s->avctx, | ||||
| "only <= 8 bits/component or " | |||||
| "16-bit gray accepted for JPEG-LS\n", 0); | |||||
| "For JPEG-LS anything except <= 8 bits/component" | |||||
| " or 16-bit gray", 0); | |||||
| return AVERROR_PATCHWELCOME; | return AVERROR_PATCHWELCOME; | ||||
| } | } | ||||
| s->nb_components = nb_components; | s->nb_components = nb_components; | ||||
| @@ -286,8 +286,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) | |||||
| } | } | ||||
| if (s->ls && (s->h_max > 1 || s->v_max > 1)) { | if (s->ls && (s->h_max > 1 || s->v_max > 1)) { | ||||
| av_log_missing_feature(s->avctx, | |||||
| "Subsampling in JPEG-LS is not supported.\n", 0); | |||||
| av_log_missing_feature(s->avctx, "Subsampling in JPEG-LS", 0); | |||||
| return AVERROR_PATCHWELCOME; | return AVERROR_PATCHWELCOME; | ||||
| } | } | ||||
| @@ -83,6 +83,12 @@ static void float_to_int16_altivec(int16_t *dst, const float *src, long len) | |||||
| } | } | ||||
| } | } | ||||
| #define VSTE_INC(dst, v, elem, inc) do { \ | |||||
| vector signed short s = vec_splat(v, elem); \ | |||||
| vec_ste(s, 0, dst); \ | |||||
| dst += inc; \ | |||||
| } while (0) | |||||
| static void float_to_int16_stride_altivec(int16_t *dst, const float *src, | static void float_to_int16_stride_altivec(int16_t *dst, const float *src, | ||||
| long len, int stride) | long len, int stride) | ||||
| { | { | ||||
| @@ -91,22 +97,14 @@ static void float_to_int16_stride_altivec(int16_t *dst, const float *src, | |||||
| for (i = 0; i < len - 7; i += 8) { | for (i = 0; i < len - 7; i += 8) { | ||||
| d = float_to_int16_one_altivec(src + i); | d = float_to_int16_one_altivec(src + i); | ||||
| #define ASSIGN_S_VEC_SPLAT_D(j) \ | |||||
| s = vec_splat(d, j); \ | |||||
| vec_ste(s, 0, dst); \ | |||||
| dst += stride | |||||
| ASSIGN_S_VEC_SPLAT_D(0); | |||||
| ASSIGN_S_VEC_SPLAT_D(1); | |||||
| ASSIGN_S_VEC_SPLAT_D(2); | |||||
| ASSIGN_S_VEC_SPLAT_D(3); | |||||
| ASSIGN_S_VEC_SPLAT_D(4); | |||||
| ASSIGN_S_VEC_SPLAT_D(5); | |||||
| ASSIGN_S_VEC_SPLAT_D(6); | |||||
| ASSIGN_S_VEC_SPLAT_D(7); | |||||
| #undef ASSIGN_S_VEC_SPLAT_D | |||||
| VSTE_INC(dst, d, 0, stride); | |||||
| VSTE_INC(dst, d, 1, stride); | |||||
| VSTE_INC(dst, d, 2, stride); | |||||
| VSTE_INC(dst, d, 3, stride); | |||||
| VSTE_INC(dst, d, 4, stride); | |||||
| VSTE_INC(dst, d, 5, stride); | |||||
| VSTE_INC(dst, d, 6, stride); | |||||
| VSTE_INC(dst, d, 7, stride); | |||||
| } | } | ||||
| } | } | ||||
| @@ -2429,7 +2429,7 @@ int ff_match_2uint16(const uint16_t(*tab)[2], int size, int a, int b) | |||||
| void av_log_missing_feature(void *avc, const char *feature, int want_sample) | void av_log_missing_feature(void *avc, const char *feature, int want_sample) | ||||
| { | { | ||||
| av_log(avc, AV_LOG_WARNING, "%s not implemented. Update your FFmpeg " | |||||
| av_log(avc, AV_LOG_WARNING, "%s is not implemented. Update your FFmpeg " | |||||
| "version to the newest one from Git. If the problem still " | "version to the newest one from Git. If the problem still " | ||||
| "occurs, it means that your file has a feature which has not " | "occurs, it means that your file has a feature which has not " | ||||
| "been implemented.\n", feature); | "been implemented.\n", feature); | ||||
| @@ -135,7 +135,7 @@ static int file_open(URLContext *h, const char *filename, int flags) | |||||
| static int64_t file_seek(URLContext *h, int64_t pos, int whence) | static int64_t file_seek(URLContext *h, int64_t pos, int whence) | ||||
| { | { | ||||
| FileContext *c = h->priv_data; | FileContext *c = h->priv_data; | ||||
| off_t ret; | |||||
| int64_t ret; | |||||
| if (whence == AVSEEK_SIZE) { | if (whence == AVSEEK_SIZE) { | ||||
| struct stat st; | struct stat st; | ||||
| @@ -75,8 +75,8 @@ static int skeleton_header(AVFormatContext *s, int idx) | |||||
| target_idx = ogg_find_stream(ogg, AV_RL32(buf+12)); | target_idx = ogg_find_stream(ogg, AV_RL32(buf+12)); | ||||
| start_granule = AV_RL64(buf+36); | start_granule = AV_RL64(buf+36); | ||||
| if (os->start_granule != OGG_NOGRANULE_VALUE) { | if (os->start_granule != OGG_NOGRANULE_VALUE) { | ||||
| av_log_missing_feature(s, "multiple fisbone for the " | |||||
| "same stream\n", 0); | |||||
| av_log_missing_feature(s, | |||||
| "multiple fisbone for the same stream", 0); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| if (target_idx >= 0 && start_granule != OGG_NOGRANULE_VALUE) { | if (target_idx >= 0 && start_granule != OGG_NOGRANULE_VALUE) { | ||||
| @@ -55,6 +55,12 @@ static RTPDynamicProtocolHandler speex_dynamic_handler = { | |||||
| .codec_id = AV_CODEC_ID_SPEEX, | .codec_id = AV_CODEC_ID_SPEEX, | ||||
| }; | }; | ||||
| static RTPDynamicProtocolHandler opus_dynamic_handler = { | |||||
| .enc_name = "opus", | |||||
| .codec_type = AVMEDIA_TYPE_AUDIO, | |||||
| .codec_id = AV_CODEC_ID_OPUS, | |||||
| }; | |||||
| /* statistics functions */ | /* statistics functions */ | ||||
| static RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL; | static RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL; | ||||
| @@ -85,6 +91,7 @@ void av_register_rtp_dynamic_payload_handlers(void) | |||||
| ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler); | ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&speex_dynamic_handler); | ff_register_dynamic_payload_handler(&speex_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&opus_dynamic_handler); | |||||
| ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); | ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler); | ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler); | ||||
| @@ -1,6 +1,7 @@ | |||||
| /* | /* | ||||
| * RTP VP8 Depacketizer | * RTP VP8 Depacketizer | ||||
| * Copyright (c) 2010 Josh Allmann | * Copyright (c) 2010 Josh Allmann | ||||
| * Copyright (c) 2012 Martin Storsjo | |||||
| * | * | ||||
| * This file is part of FFmpeg. | * This file is part of FFmpeg. | ||||
| * | * | ||||
| @@ -23,7 +24,7 @@ | |||||
| * @file | * @file | ||||
| * @brief RTP support for the VP8 payload | * @brief RTP support for the VP8 payload | ||||
| * @author Josh Allmann <joshua.allmann@gmail.com> | * @author Josh Allmann <joshua.allmann@gmail.com> | ||||
| * @see http://www.webmproject.org/code/specs/rtp/ | |||||
| * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05 | |||||
| */ | */ | ||||
| #include "libavcodec/bytestream.h" | #include "libavcodec/bytestream.h" | ||||
| @@ -33,14 +34,12 @@ | |||||
| struct PayloadContext { | struct PayloadContext { | ||||
| AVIOContext *data; | AVIOContext *data; | ||||
| uint32_t timestamp; | uint32_t timestamp; | ||||
| int is_keyframe; | |||||
| }; | }; | ||||
| static void prepare_packet(AVPacket *pkt, PayloadContext *vp8, int stream) | static void prepare_packet(AVPacket *pkt, PayloadContext *vp8, int stream) | ||||
| { | { | ||||
| av_init_packet(pkt); | av_init_packet(pkt); | ||||
| pkt->stream_index = stream; | pkt->stream_index = stream; | ||||
| pkt->flags = vp8->is_keyframe ? AV_PKT_FLAG_KEY : 0; | |||||
| pkt->size = avio_close_dyn_buf(vp8->data, &pkt->data); | pkt->size = avio_close_dyn_buf(vp8->data, &pkt->data); | ||||
| pkt->destruct = av_destruct_packet; | pkt->destruct = av_destruct_packet; | ||||
| vp8->data = NULL; | vp8->data = NULL; | ||||
| @@ -54,70 +53,84 @@ static int vp8_handle_packet(AVFormatContext *ctx, | |||||
| const uint8_t *buf, | const uint8_t *buf, | ||||
| int len, int flags) | int len, int flags) | ||||
| { | { | ||||
| int start_packet, end_packet, has_au, ret = AVERROR(EAGAIN); | |||||
| if (!buf) { | |||||
| // only called when vp8_handle_packet returns 1 | |||||
| if (!vp8->data) { | |||||
| av_log(ctx, AV_LOG_ERROR, "Invalid VP8 data passed\n"); | |||||
| int start_partition, end_packet; | |||||
| int extended_bits, non_ref, part_id; | |||||
| int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0, | |||||
| keyidx_present = 0; | |||||
| int pictureid = -1, keyidx = -1; | |||||
| if (len < 1) | |||||
| return AVERROR_INVALIDDATA; | |||||
| extended_bits = buf[0] & 0x80; | |||||
| non_ref = buf[0] & 0x20; | |||||
| start_partition = buf[0] & 0x10; | |||||
| part_id = buf[0] & 0x0f; | |||||
| end_packet = flags & RTP_FLAG_MARKER; | |||||
| buf++; | |||||
| len--; | |||||
| if (extended_bits) { | |||||
| if (len < 1) | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| pictureid_present = buf[0] & 0x80; | |||||
| tl0picidx_present = buf[0] & 0x40; | |||||
| tid_present = buf[0] & 0x20; | |||||
| keyidx_present = buf[0] & 0x10; | |||||
| buf++; | |||||
| len--; | |||||
| } | |||||
| if (pictureid_present) { | |||||
| if (len < 1) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (buf[0] & 0x80) { | |||||
| if (len < 2) | |||||
| return AVERROR_INVALIDDATA; | |||||
| pictureid = AV_RB16(buf) & 0x7fff; | |||||
| buf += 2; | |||||
| len -= 2; | |||||
| } else { | |||||
| pictureid = buf[0] & 0x7f; | |||||
| buf++; | |||||
| len--; | |||||
| } | } | ||||
| prepare_packet(pkt, vp8, st->index); | |||||
| *timestamp = vp8->timestamp; | |||||
| return 0; | |||||
| } | } | ||||
| if (tl0picidx_present) { | |||||
| // Ignoring temporal level zero index | |||||
| buf++; | |||||
| len--; | |||||
| } | |||||
| if (tid_present || keyidx_present) { | |||||
| // Ignoring temporal layer index and layer sync bit | |||||
| if (len < 1) | |||||
| return AVERROR_INVALIDDATA; | |||||
| if (keyidx_present) | |||||
| keyidx = buf[0] & 0x1f; | |||||
| buf++; | |||||
| len--; | |||||
| } | |||||
| if (len < 1) | |||||
| return AVERROR_INVALIDDATA; | |||||
| start_packet = *buf & 1; | |||||
| end_packet = flags & RTP_FLAG_MARKER; | |||||
| has_au = *buf & 2; | |||||
| buf++; | |||||
| len--; | |||||
| if (start_packet) { | |||||
| if (start_partition && part_id == 0) { | |||||
| int res; | int res; | ||||
| uint32_t ts = *timestamp; | |||||
| if (vp8->data) { | if (vp8->data) { | ||||
| // missing end marker; return old frame anyway. untested | |||||
| prepare_packet(pkt, vp8, st->index); | |||||
| *timestamp = vp8->timestamp; // reset timestamp from old frame | |||||
| // if current frame fits into one rtp packet, need to hold | |||||
| // that for the next av_get_packet call | |||||
| ret = end_packet ? 1 : 0; | |||||
| uint8_t *tmp; | |||||
| avio_close_dyn_buf(vp8->data, &tmp); | |||||
| av_free(tmp); | |||||
| vp8->data = NULL; | |||||
| } | } | ||||
| if ((res = avio_open_dyn_buf(&vp8->data)) < 0) | if ((res = avio_open_dyn_buf(&vp8->data)) < 0) | ||||
| return res; | return res; | ||||
| vp8->is_keyframe = *buf & 1; | |||||
| vp8->timestamp = ts; | |||||
| vp8->timestamp = *timestamp; | |||||
| } | } | ||||
| if (!vp8->data || vp8->timestamp != *timestamp && ret == AVERROR(EAGAIN)) { | |||||
| if (!vp8->data || vp8->timestamp != *timestamp) { | |||||
| av_log(ctx, AV_LOG_WARNING, | av_log(ctx, AV_LOG_WARNING, | ||||
| "Received no start marker; dropping frame\n"); | "Received no start marker; dropping frame\n"); | ||||
| return AVERROR(EAGAIN); | return AVERROR(EAGAIN); | ||||
| } | } | ||||
| // cycle through VP8AU headers if needed | |||||
| // not tested with actual VP8AUs | |||||
| while (len) { | |||||
| int au_len = len; | |||||
| if (has_au && len > 2) { | |||||
| au_len = AV_RB16(buf); | |||||
| buf += 2; | |||||
| len -= 2; | |||||
| if (buf + au_len > buf + len) { | |||||
| av_log(ctx, AV_LOG_ERROR, "Invalid VP8AU length\n"); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| } | |||||
| avio_write(vp8->data, buf, au_len); | |||||
| buf += au_len; | |||||
| len -= au_len; | |||||
| } | |||||
| if (ret != AVERROR(EAGAIN)) // did we miss a end marker? | |||||
| return ret; | |||||
| avio_write(vp8->data, buf, len); | |||||
| if (end_packet) { | if (end_packet) { | ||||
| prepare_packet(pkt, vp8, st->index); | prepare_packet(pkt, vp8, st->index); | ||||
| @@ -129,8 +142,6 @@ static int vp8_handle_packet(AVFormatContext *ctx, | |||||
| static PayloadContext *vp8_new_context(void) | static PayloadContext *vp8_new_context(void) | ||||
| { | { | ||||
| av_log(NULL, AV_LOG_ERROR, "RTP VP8 payload implementation is incompatible " | |||||
| "with the latest spec drafts.\n"); | |||||
| return av_mallocz(sizeof(PayloadContext)); | return av_mallocz(sizeof(PayloadContext)); | ||||
| } | } | ||||
| @@ -77,6 +77,7 @@ static int is_supported(enum AVCodecID id) | |||||
| case AV_CODEC_ID_ILBC: | case AV_CODEC_ID_ILBC: | ||||
| case AV_CODEC_ID_MJPEG: | case AV_CODEC_ID_MJPEG: | ||||
| case AV_CODEC_ID_SPEEX: | case AV_CODEC_ID_SPEEX: | ||||
| case AV_CODEC_ID_OPUS: | |||||
| return 1; | return 1; | ||||
| default: | default: | ||||
| return 0; | return 0; | ||||
| @@ -181,15 +182,21 @@ static int rtp_write_header(AVFormatContext *s1) | |||||
| s->max_payload_size -= 6; // ident+frag+tdt/vdt+pkt_num+pkt_length | s->max_payload_size -= 6; // ident+frag+tdt/vdt+pkt_num+pkt_length | ||||
| s->num_frames = 0; | s->num_frames = 0; | ||||
| goto defaultcase; | goto defaultcase; | ||||
| case AV_CODEC_ID_VP8: | |||||
| av_log(s1, AV_LOG_ERROR, "RTP VP8 payload implementation is " | |||||
| "incompatible with the latest spec drafts.\n"); | |||||
| break; | |||||
| case AV_CODEC_ID_ADPCM_G722: | case AV_CODEC_ID_ADPCM_G722: | ||||
| /* Due to a historical error, the clock rate for G722 in RTP is | /* Due to a historical error, the clock rate for G722 in RTP is | ||||
| * 8000, even if the sample rate is 16000. See RFC 3551. */ | * 8000, even if the sample rate is 16000. See RFC 3551. */ | ||||
| avpriv_set_pts_info(st, 32, 1, 8000); | avpriv_set_pts_info(st, 32, 1, 8000); | ||||
| break; | break; | ||||
| case AV_CODEC_ID_OPUS: | |||||
| if (st->codec->channels > 2) { | |||||
| av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n"); | |||||
| goto fail; | |||||
| } | |||||
| /* The opus RTP RFC says that all opus streams should use 48000 Hz | |||||
| * as clock rate, since all opus sample rates can be expressed in | |||||
| * this clock rate, and sample rate changes on the fly are supported. */ | |||||
| avpriv_set_pts_info(st, 32, 1, 48000); | |||||
| break; | |||||
| case AV_CODEC_ID_ILBC: | case AV_CODEC_ID_ILBC: | ||||
| if (st->codec->block_align != 38 && st->codec->block_align != 50) { | if (st->codec->block_align != 38 && st->codec->block_align != 50) { | ||||
| av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n"); | av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n"); | ||||
| @@ -529,6 +536,14 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) | |||||
| case AV_CODEC_ID_MJPEG: | case AV_CODEC_ID_MJPEG: | ||||
| ff_rtp_send_jpeg(s1, pkt->data, size); | ff_rtp_send_jpeg(s1, pkt->data, size); | ||||
| break; | break; | ||||
| case AV_CODEC_ID_OPUS: | |||||
| if (size > s->max_payload_size) { | |||||
| av_log(s1, AV_LOG_ERROR, | |||||
| "Packet size %d too large for max RTP payload size %d\n", | |||||
| size, s->max_payload_size); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| /* Intentional fallthrough */ | |||||
| 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); | ||||
| @@ -22,7 +22,7 @@ | |||||
| #include "rtpenc.h" | #include "rtpenc.h" | ||||
| /* Based on a draft spec for VP8 RTP. | /* Based on a draft spec for VP8 RTP. | ||||
| * ( http://www.webmproject.org/code/specs/rtp/ ) */ | |||||
| * ( http://tools.ietf.org/html/draft-ietf-payload-vp8-05 ) */ | |||||
| void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size) | void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size) | ||||
| { | { | ||||
| RTPMuxContext *s = s1->priv_data; | RTPMuxContext *s = s1->priv_data; | ||||
| @@ -32,7 +32,9 @@ void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size) | |||||
| s->timestamp = s->cur_timestamp; | s->timestamp = s->cur_timestamp; | ||||
| max_packet_size = s->max_payload_size - 1; // minus one for header byte | max_packet_size = s->max_payload_size - 1; // minus one for header byte | ||||
| *s->buf_ptr++ = 1; // 0b1 indicates start of frame | |||||
| // no extended control bits, reference frame, start of partition, | |||||
| // partition id 0 | |||||
| *s->buf_ptr++ = 0x10; | |||||
| while (size > 0) { | while (size > 0) { | ||||
| len = FFMIN(size, max_packet_size); | len = FFMIN(size, max_packet_size); | ||||
| @@ -576,6 +576,10 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, | |||||
| av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", | av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", | ||||
| payload_type, c->sample_rate); | payload_type, c->sample_rate); | ||||
| break; | break; | ||||
| case AV_CODEC_ID_OPUS: | |||||
| av_strlcatf(buff, size, "a=rtpmap:%d opus/48000\r\n", | |||||
| payload_type); | |||||
| break; | |||||
| default: | default: | ||||
| /* Nothing special to do here... */ | /* Nothing special to do here... */ | ||||
| break; | break; | ||||
| @@ -100,6 +100,8 @@ OBJS-$(HAVE_BROKEN_SNPRINTF) += ../compat/msvcrt/snprintf.o | |||||
| OBJS-$(HAVE_MSVCRT) += ../compat/strtod.o | OBJS-$(HAVE_MSVCRT) += ../compat/strtod.o | ||||
| SKIPHEADERS = old_pix_fmts.h | |||||
| TESTPROGS = adler32 \ | TESTPROGS = adler32 \ | ||||
| aes \ | aes \ | ||||
| avstring \ | avstring \ | ||||