* qatar/master: matroska: Clear prev_pkt between seeks. avutil: change default buffer size alignment for sample buffer functions audemux: Add a sanity check for the number of channels Remove libdirac decoder. matroska: Add incremental parsing of clusters. avconv: fix off by one check in complex_filter mpegts: Try seeking back even for nonseekable protocols swscale: K&R formatting cosmetics (part III) Conflicts: configure doc/general.texi doc/platform.texi ffmpeg.c libavcodec/Makefile libavcodec/allcodecs.c libavcodec/libdirac.h libavcodec/libdiracdec.c libavformat/au.c libavformat/mpegts.c libswscale/input.c tests/ref/seek/lavf_mkv Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.11
| @@ -179,7 +179,6 @@ External library support: | |||||
| --enable-libcdio enable audio CD grabbing with libcdio | --enable-libcdio enable audio CD grabbing with libcdio | ||||
| --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394 | --enable-libdc1394 enable IIDC-1394 grabbing using libdc1394 | ||||
| and libraw1394 [no] | and libraw1394 [no] | ||||
| --enable-libdirac enable Dirac support via libdirac [no] | |||||
| --enable-libfaac enable FAAC support via libfaac [no] | --enable-libfaac enable FAAC support via libfaac [no] | ||||
| --enable-libfreetype enable libfreetype [no] | --enable-libfreetype enable libfreetype [no] | ||||
| --enable-libgsm enable GSM support via libgsm [no] | --enable-libgsm enable GSM support via libgsm [no] | ||||
| @@ -1035,7 +1034,6 @@ CONFIG_LIST=" | |||||
| libcdio | libcdio | ||||
| libcelt | libcelt | ||||
| libdc1394 | libdc1394 | ||||
| libdirac | |||||
| libfaac | libfaac | ||||
| libfreetype | libfreetype | ||||
| libgsm | libgsm | ||||
| @@ -1557,7 +1555,6 @@ h264_parser_select="golomb h264dsp h264pred" | |||||
| # external libraries | # external libraries | ||||
| libaacplus_encoder_deps="libaacplus" | libaacplus_encoder_deps="libaacplus" | ||||
| libcelt_decoder_deps="libcelt" | libcelt_decoder_deps="libcelt" | ||||
| libdirac_decoder_deps="libdirac !libschroedinger" | |||||
| libfaac_encoder_deps="libfaac" | libfaac_encoder_deps="libfaac" | ||||
| libgsm_decoder_deps="libgsm" | libgsm_decoder_deps="libgsm" | ||||
| libgsm_encoder_deps="libgsm" | libgsm_encoder_deps="libgsm" | ||||
| @@ -3200,9 +3197,6 @@ enabled libbluray && require libbluray libbluray/bluray.h bd_open -lbluray | |||||
| enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && | enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && | ||||
| { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 || | { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 || | ||||
| die "ERROR: libcelt version must be >= 0.11.0."; } | die "ERROR: libcelt version must be >= 0.11.0."; } | ||||
| enabled libdirac && require_pkg_config dirac \ | |||||
| "libdirac_decoder/dirac_parser.h" \ | |||||
| "dirac_decoder_init" | |||||
| enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac | enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac | ||||
| enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType | enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType | ||||
| enabled libgsm && require libgsm gsm/gsm.h gsm_create -lgsm | enabled libgsm && require libgsm gsm/gsm.h gsm_create -lgsm | ||||
| @@ -3572,7 +3566,6 @@ echo "libass enabled ${libass-no}" | |||||
| echo "libcdio support ${libcdio-no}" | echo "libcdio support ${libcdio-no}" | ||||
| echo "libcelt enabled ${libcelt-no}" | echo "libcelt enabled ${libcelt-no}" | ||||
| echo "libdc1394 support ${libdc1394-no}" | echo "libdc1394 support ${libdc1394-no}" | ||||
| echo "libdirac enabled ${libdirac-no}" | |||||
| echo "libfaac enabled ${libfaac-no}" | echo "libfaac enabled ${libfaac-no}" | ||||
| echo "libgsm enabled ${libgsm-no}" | echo "libgsm enabled ${libgsm-no}" | ||||
| echo "libmodplug enabled ${libmodplug-no}" | echo "libmodplug enabled ${libmodplug-no}" | ||||
| @@ -482,7 +482,7 @@ following image formats are supported: | |||||
| @item DFA @tab @tab X | @item DFA @tab @tab X | ||||
| @tab Codec used in Chronomaster game. | @tab Codec used in Chronomaster game. | ||||
| @item Dirac @tab E @tab X | @item Dirac @tab E @tab X | ||||
| @tab supported through external libdirac/libschroedinger libraries | |||||
| @tab supported through external library libschroedinger | |||||
| @item Deluxe Paint Animation @tab @tab X | @item Deluxe Paint Animation @tab @tab X | ||||
| @item DNxHD @tab X @tab X | @item DNxHD @tab X @tab X | ||||
| @tab aka SMPTE VC3 | @tab aka SMPTE VC3 | ||||
| @@ -354,9 +354,8 @@ These library packages are only available from | |||||
| @uref{http://sourceware.org/cygwinports/, Cygwin Ports}: | @uref{http://sourceware.org/cygwinports/, Cygwin Ports}: | ||||
| @example | @example | ||||
| yasm, libSDL-devel, libdirac-devel, libfaac-devel, libaacplus-devel, libgsm-devel, | |||||
| libmp3lame-devel, libschroedinger1.0-devel, speex-devel, libtheora-devel, | |||||
| libxvidcore-devel | |||||
| yasm, libSDL-devel, libfaac-devel, libaacplus-devel, libgsm-devel, libmp3lame-devel, | |||||
| libschroedinger1.0-devel, speex-devel, libtheora-devel, libxvidcore-devel | |||||
| @end example | @end example | ||||
| The recommendation for libnut and x264 is to build them from source by | The recommendation for libnut and x264 is to build them from source by | ||||
| @@ -634,7 +634,6 @@ OBJS-$(CONFIG_WTV_DEMUXER) += mpeg4audio.o mpegaudiodata.o | |||||
| # external codec libraries | # external codec libraries | ||||
| OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o | OBJS-$(CONFIG_LIBAACPLUS_ENCODER) += libaacplus.o | ||||
| OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o | OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o | ||||
| OBJS-$(CONFIG_LIBDIRAC_DECODER) += libdiracdec.o | |||||
| OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o audio_frame_queue.o | OBJS-$(CONFIG_LIBFAAC_ENCODER) += libfaac.o audio_frame_queue.o | ||||
| OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o | OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o | ||||
| OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o | OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o | ||||
| @@ -753,7 +752,6 @@ SKIPHEADERS += %_tablegen.h \ | |||||
| tableprint.h \ | tableprint.h \ | ||||
| $(ARCH)/vp56_arith.h | $(ARCH)/vp56_arith.h | ||||
| SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h | SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h | ||||
| SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h | |||||
| SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h | SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h | ||||
| SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h | SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h | ||||
| SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h | SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h | ||||
| @@ -403,7 +403,6 @@ void avcodec_register_all(void) | |||||
| /* external libraries */ | /* external libraries */ | ||||
| REGISTER_DECODER (LIBCELT, libcelt); | REGISTER_DECODER (LIBCELT, libcelt); | ||||
| REGISTER_DECODER (LIBDIRAC, libdirac); | |||||
| REGISTER_ENCODER (LIBFAAC, libfaac); | REGISTER_ENCODER (LIBFAAC, libfaac); | ||||
| REGISTER_ENCDEC (LIBGSM, libgsm); | REGISTER_ENCDEC (LIBGSM, libgsm); | ||||
| REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); | REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); | ||||
| @@ -1,44 +0,0 @@ | |||||
| /* | |||||
| * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > | |||||
| * | |||||
| * 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 | |||||
| * data structures common to libdirac encoder and decoder | |||||
| */ | |||||
| #ifndef AVCODEC_LIBDIRAC_H | |||||
| #define AVCODEC_LIBDIRAC_H | |||||
| #include "avcodec.h" | |||||
| #include <libdirac_common/dirac_types.h> | |||||
| /** | |||||
| * Table providing a Dirac chroma format to FFmpeg pixel format mapping. | |||||
| */ | |||||
| static const struct { | |||||
| enum PixelFormat ff_pix_fmt; | |||||
| dirac_chroma_t dirac_pix_fmt; | |||||
| } dirac_pixel_format_map[] = { | |||||
| { PIX_FMT_YUV420P, format420 }, | |||||
| { PIX_FMT_YUV422P, format422 }, | |||||
| { PIX_FMT_YUV444P, format444 }, | |||||
| }; | |||||
| #endif /* AVCODEC_LIBDIRAC_H */ | |||||
| @@ -1,208 +0,0 @@ | |||||
| /* | |||||
| * Dirac decoder support via libdirac library | |||||
| * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk> | |||||
| * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > | |||||
| * | |||||
| * 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 | |||||
| * Dirac decoder support via libdirac library; more details about the Dirac | |||||
| * project can be found at http://dirac.sourceforge.net/. | |||||
| * The libdirac_decoder library implements Dirac specification version 2.2 | |||||
| * (http://dirac.sourceforge.net/specification.html). | |||||
| */ | |||||
| #include "libavutil/imgutils.h" | |||||
| #include "libdirac.h" | |||||
| #undef NDEBUG | |||||
| #include <assert.h> | |||||
| #include <libdirac_decoder/dirac_parser.h> | |||||
| /** contains a single frame returned from Dirac */ | |||||
| typedef struct DiracDecoderParams { | |||||
| /** decoder handle */ | |||||
| dirac_decoder_t* p_decoder; | |||||
| /** buffer to hold decoded frame */ | |||||
| unsigned char* p_out_frame_buf; | |||||
| } DiracDecoderParams; | |||||
| /** | |||||
| * returns FFmpeg chroma format | |||||
| */ | |||||
| static enum PixelFormat get_chroma_format(dirac_chroma_t dirac_pix_fmt) | |||||
| { | |||||
| int num_formats = sizeof(dirac_pixel_format_map) / | |||||
| sizeof(dirac_pixel_format_map[0]); | |||||
| int idx; | |||||
| for (idx = 0; idx < num_formats; ++idx) | |||||
| if (dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt) | |||||
| return dirac_pixel_format_map[idx].ff_pix_fmt; | |||||
| return PIX_FMT_NONE; | |||||
| } | |||||
| static av_cold int libdirac_decode_init(AVCodecContext *avccontext) | |||||
| { | |||||
| DiracDecoderParams *p_dirac_params = avccontext->priv_data; | |||||
| p_dirac_params->p_decoder = dirac_decoder_init(avccontext->debug); | |||||
| if (!p_dirac_params->p_decoder) | |||||
| return -1; | |||||
| return 0; | |||||
| } | |||||
| static int libdirac_decode_frame(AVCodecContext *avccontext, | |||||
| void *data, int *data_size, | |||||
| AVPacket *avpkt) | |||||
| { | |||||
| const uint8_t *buf = avpkt->data; | |||||
| int buf_size = avpkt->size; | |||||
| DiracDecoderParams *p_dirac_params = avccontext->priv_data; | |||||
| AVPicture *picture = data; | |||||
| AVPicture pic; | |||||
| int pict_size; | |||||
| unsigned char *buffer[3]; | |||||
| *data_size = 0; | |||||
| if (buf_size > 0) { | |||||
| /* set data to decode into buffer */ | |||||
| dirac_buffer(p_dirac_params->p_decoder, buf, buf + buf_size); | |||||
| if ((buf[4] & 0x08) == 0x08 && (buf[4] & 0x03)) | |||||
| avccontext->has_b_frames = 1; | |||||
| } | |||||
| while (1) { | |||||
| /* parse data and process result */ | |||||
| DecoderState state = dirac_parse(p_dirac_params->p_decoder); | |||||
| switch (state) { | |||||
| case STATE_BUFFER: | |||||
| return buf_size; | |||||
| case STATE_SEQUENCE: | |||||
| { | |||||
| /* tell FFmpeg about sequence details */ | |||||
| dirac_sourceparams_t *src_params = &p_dirac_params->p_decoder->src_params; | |||||
| if (av_image_check_size(src_params->width, src_params->height, | |||||
| 0, avccontext) < 0) { | |||||
| av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n", | |||||
| src_params->width, src_params->height); | |||||
| avccontext->height = avccontext->width = 0; | |||||
| return -1; | |||||
| } | |||||
| avccontext->height = src_params->height; | |||||
| avccontext->width = src_params->width; | |||||
| avccontext->pix_fmt = get_chroma_format(src_params->chroma); | |||||
| if (avccontext->pix_fmt == PIX_FMT_NONE) { | |||||
| av_log(avccontext, AV_LOG_ERROR, | |||||
| "Dirac chroma format %d not supported currently\n", | |||||
| src_params->chroma); | |||||
| return -1; | |||||
| } | |||||
| avccontext->time_base.den = src_params->frame_rate.numerator; | |||||
| avccontext->time_base.num = src_params->frame_rate.denominator; | |||||
| /* calculate output dimensions */ | |||||
| avpicture_fill(&pic, NULL, avccontext->pix_fmt, | |||||
| avccontext->width, avccontext->height); | |||||
| pict_size = avpicture_get_size(avccontext->pix_fmt, | |||||
| avccontext->width, | |||||
| avccontext->height); | |||||
| /* allocate output buffer */ | |||||
| if (!p_dirac_params->p_out_frame_buf) | |||||
| p_dirac_params->p_out_frame_buf = av_malloc(pict_size); | |||||
| buffer[0] = p_dirac_params->p_out_frame_buf; | |||||
| buffer[1] = p_dirac_params->p_out_frame_buf + | |||||
| pic.linesize[0] * avccontext->height; | |||||
| buffer[2] = buffer[1] + | |||||
| pic.linesize[1] * src_params->chroma_height; | |||||
| /* tell Dirac about output destination */ | |||||
| dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL); | |||||
| break; | |||||
| } | |||||
| case STATE_SEQUENCE_END: | |||||
| break; | |||||
| case STATE_PICTURE_AVAIL: | |||||
| /* fill picture with current buffer data from Dirac */ | |||||
| avpicture_fill(picture, p_dirac_params->p_out_frame_buf, | |||||
| avccontext->pix_fmt, | |||||
| avccontext->width, avccontext->height); | |||||
| *data_size = sizeof(AVPicture); | |||||
| return buf_size; | |||||
| case STATE_INVALID: | |||||
| return -1; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| return buf_size; | |||||
| } | |||||
| static av_cold int libdirac_decode_close(AVCodecContext *avccontext) | |||||
| { | |||||
| DiracDecoderParams *p_dirac_params = avccontext->priv_data; | |||||
| dirac_decoder_close(p_dirac_params->p_decoder); | |||||
| av_freep(&p_dirac_params->p_out_frame_buf); | |||||
| return 0; | |||||
| } | |||||
| static void libdirac_flush(AVCodecContext *avccontext) | |||||
| { | |||||
| /* Got a seek request. We will need free memory held in the private | |||||
| * context and free the current Dirac decoder handle and then open | |||||
| * a new decoder handle. */ | |||||
| libdirac_decode_close(avccontext); | |||||
| libdirac_decode_init(avccontext); | |||||
| return; | |||||
| } | |||||
| AVCodec ff_libdirac_decoder = { | |||||
| .name = "libdirac", | |||||
| .type = AVMEDIA_TYPE_VIDEO, | |||||
| .id = CODEC_ID_DIRAC, | |||||
| .priv_data_size = sizeof(DiracDecoderParams), | |||||
| .init = libdirac_decode_init, | |||||
| .close = libdirac_decode_close, | |||||
| .decode = libdirac_decode_frame, | |||||
| .capabilities = CODEC_CAP_DELAY, | |||||
| .flush = libdirac_flush, | |||||
| .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"), | |||||
| }; | |||||
| @@ -150,7 +150,7 @@ static int au_read_header(AVFormatContext *s) | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| if (channels <= 0) { | |||||
| if (channels == 0 || channels > 64) { | |||||
| av_log(s, AV_LOG_ERROR, "Invalid number of channels %d\n", channels); | av_log(s, AV_LOG_ERROR, "Invalid number of channels %d\n", channels); | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| @@ -223,6 +223,11 @@ typedef struct { | |||||
| uint64_t length; | uint64_t length; | ||||
| } MatroskaLevel; | } MatroskaLevel; | ||||
| typedef struct { | |||||
| uint64_t timecode; | |||||
| EbmlList blocks; | |||||
| } MatroskaCluster; | |||||
| typedef struct { | typedef struct { | ||||
| AVFormatContext *ctx; | AVFormatContext *ctx; | ||||
| @@ -259,6 +264,13 @@ typedef struct { | |||||
| /* File has a CUES element, but we defer parsing until it is needed. */ | /* File has a CUES element, but we defer parsing until it is needed. */ | ||||
| int cues_parsing_deferred; | int cues_parsing_deferred; | ||||
| int current_cluster_num_blocks; | |||||
| int64_t current_cluster_pos; | |||||
| MatroskaCluster current_cluster; | |||||
| /* File has SSA subtitles which prevent incremental cluster parsing. */ | |||||
| int contains_ssa; | |||||
| } MatroskaDemuxContext; | } MatroskaDemuxContext; | ||||
| typedef struct { | typedef struct { | ||||
| @@ -268,11 +280,6 @@ typedef struct { | |||||
| EbmlBin bin; | EbmlBin bin; | ||||
| } MatroskaBlock; | } MatroskaBlock; | ||||
| typedef struct { | |||||
| uint64_t timecode; | |||||
| EbmlList blocks; | |||||
| } MatroskaCluster; | |||||
| static EbmlSyntax ebml_header[] = { | static EbmlSyntax ebml_header[] = { | ||||
| { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} }, | { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, offsetof(Ebml,version), {.u=EBML_VERSION} }, | ||||
| { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} }, | { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, offsetof(Ebml,max_size), {.u=8} }, | ||||
| @@ -543,6 +550,38 @@ static EbmlSyntax matroska_clusters[] = { | |||||
| { 0 } | { 0 } | ||||
| }; | }; | ||||
| static EbmlSyntax matroska_cluster_incremental_parsing[] = { | |||||
| { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, | |||||
| { MATROSKA_ID_BLOCKGROUP, EBML_NEST, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, | |||||
| { MATROSKA_ID_SIMPLEBLOCK, EBML_PASS, sizeof(MatroskaBlock), offsetof(MatroskaCluster,blocks), {.n=matroska_blockgroup} }, | |||||
| { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, | |||||
| { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, | |||||
| { MATROSKA_ID_INFO, EBML_NONE }, | |||||
| { MATROSKA_ID_CUES, EBML_NONE }, | |||||
| { MATROSKA_ID_TAGS, EBML_NONE }, | |||||
| { MATROSKA_ID_SEEKHEAD, EBML_NONE }, | |||||
| { MATROSKA_ID_CLUSTER, EBML_STOP }, | |||||
| { 0 } | |||||
| }; | |||||
| static EbmlSyntax matroska_cluster_incremental[] = { | |||||
| { MATROSKA_ID_CLUSTERTIMECODE,EBML_UINT,0, offsetof(MatroskaCluster,timecode) }, | |||||
| { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, | |||||
| { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, | |||||
| { MATROSKA_ID_CLUSTERPOSITION,EBML_NONE }, | |||||
| { MATROSKA_ID_CLUSTERPREVSIZE,EBML_NONE }, | |||||
| { 0 } | |||||
| }; | |||||
| static EbmlSyntax matroska_clusters_incremental[] = { | |||||
| { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, {.n=matroska_cluster_incremental} }, | |||||
| { MATROSKA_ID_INFO, EBML_NONE }, | |||||
| { MATROSKA_ID_CUES, EBML_NONE }, | |||||
| { MATROSKA_ID_TAGS, EBML_NONE }, | |||||
| { MATROSKA_ID_SEEKHEAD, EBML_NONE }, | |||||
| { 0 } | |||||
| }; | |||||
| static const char *const matroska_doctypes[] = { "matroska", "webm" }; | static const char *const matroska_doctypes[] = { "matroska", "webm" }; | ||||
| static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) | static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) | ||||
| @@ -1693,6 +1732,8 @@ static int matroska_read_header(AVFormatContext *s) | |||||
| st->need_parsing = AVSTREAM_PARSE_HEADERS; | st->need_parsing = AVSTREAM_PARSE_HEADERS; | ||||
| } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { | } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { | ||||
| st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; | st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; | ||||
| if (st->codec->codec_id == CODEC_ID_SSA) | |||||
| matroska->contains_ssa = 1; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1766,6 +1807,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, | |||||
| matroska->packets = newpackets; | matroska->packets = newpackets; | ||||
| } else { | } else { | ||||
| av_freep(&matroska->packets); | av_freep(&matroska->packets); | ||||
| matroska->prev_pkt = NULL; | |||||
| } | } | ||||
| matroska->num_packets--; | matroska->num_packets--; | ||||
| return 0; | return 0; | ||||
| @@ -1822,6 +1864,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, | |||||
| st = track->stream; | st = track->stream; | ||||
| if (st->discard >= AVDISCARD_ALL) | if (st->discard >= AVDISCARD_ALL) | ||||
| return res; | return res; | ||||
| av_assert1(duration != AV_NOPTS_VALUE); | |||||
| if (!duration) | if (!duration) | ||||
| duration = track->default_duration / matroska->time_scale; | duration = track->default_duration / matroska->time_scale; | ||||
| @@ -2066,13 +2109,71 @@ end: | |||||
| return res; | return res; | ||||
| } | } | ||||
| static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) | |||||
| { | |||||
| EbmlList *blocks_list; | |||||
| MatroskaBlock *blocks; | |||||
| int i, res; | |||||
| res = ebml_parse(matroska, | |||||
| matroska_cluster_incremental_parsing, | |||||
| &matroska->current_cluster); | |||||
| if (res == 1) { | |||||
| /* New Cluster */ | |||||
| if (matroska->current_cluster_pos) | |||||
| ebml_level_end(matroska); | |||||
| ebml_free(matroska_cluster, &matroska->current_cluster); | |||||
| memset(&matroska->current_cluster, 0, sizeof(MatroskaCluster)); | |||||
| matroska->current_cluster_num_blocks = 0; | |||||
| matroska->current_cluster_pos = avio_tell(matroska->ctx->pb); | |||||
| matroska->prev_pkt = NULL; | |||||
| /* sizeof the ID which was already read */ | |||||
| if (matroska->current_id) | |||||
| matroska->current_cluster_pos -= 4; | |||||
| res = ebml_parse(matroska, | |||||
| matroska_clusters_incremental, | |||||
| &matroska->current_cluster); | |||||
| /* Try parsing the block again. */ | |||||
| if (res == 1) | |||||
| res = ebml_parse(matroska, | |||||
| matroska_cluster_incremental_parsing, | |||||
| &matroska->current_cluster); | |||||
| } | |||||
| if (!res && | |||||
| matroska->current_cluster_num_blocks < | |||||
| matroska->current_cluster.blocks.nb_elem) { | |||||
| blocks_list = &matroska->current_cluster.blocks; | |||||
| blocks = blocks_list->elem; | |||||
| matroska->current_cluster_num_blocks = blocks_list->nb_elem; | |||||
| i = blocks_list->nb_elem - 1; | |||||
| if (blocks[i].bin.size > 0 && blocks[i].bin.data) { | |||||
| int is_keyframe = blocks[i].non_simple ? !blocks[i].reference : -1; | |||||
| if (!blocks[i].non_simple) | |||||
| blocks[i].duration = 0; | |||||
| res = matroska_parse_block(matroska, | |||||
| blocks[i].bin.data, blocks[i].bin.size, | |||||
| blocks[i].bin.pos, | |||||
| matroska->current_cluster.timecode, | |||||
| blocks[i].duration, is_keyframe, | |||||
| matroska->current_cluster_pos); | |||||
| } | |||||
| } | |||||
| if (res < 0) matroska->done = 1; | |||||
| return res; | |||||
| } | |||||
| static int matroska_parse_cluster(MatroskaDemuxContext *matroska) | static int matroska_parse_cluster(MatroskaDemuxContext *matroska) | ||||
| { | { | ||||
| MatroskaCluster cluster = { 0 }; | MatroskaCluster cluster = { 0 }; | ||||
| EbmlList *blocks_list; | EbmlList *blocks_list; | ||||
| MatroskaBlock *blocks; | MatroskaBlock *blocks; | ||||
| int i, res; | int i, res; | ||||
| int64_t pos = avio_tell(matroska->ctx->pb); | |||||
| int64_t pos; | |||||
| if (!matroska->contains_ssa) | |||||
| return matroska_parse_cluster_incremental(matroska); | |||||
| pos = avio_tell(matroska->ctx->pb); | |||||
| matroska->prev_pkt = NULL; | matroska->prev_pkt = NULL; | ||||
| if (matroska->current_id) | if (matroska->current_id) | ||||
| pos -= 4; /* sizeof the ID which was already read */ | pos -= 4; /* sizeof the ID which was already read */ | ||||
| @@ -2129,6 +2230,7 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, | |||||
| avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET); | avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET); | ||||
| matroska->current_id = 0; | matroska->current_id = 0; | ||||
| while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { | while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) { | ||||
| matroska->prev_pkt = NULL; | |||||
| matroska_clear_queue(matroska); | matroska_clear_queue(matroska); | ||||
| if (matroska_parse_cluster(matroska) < 0) | if (matroska_parse_cluster(matroska) < 0) | ||||
| break; | break; | ||||
| @@ -2187,6 +2289,7 @@ static int matroska_read_close(AVFormatContext *s) | |||||
| for (n=0; n < matroska->tracks.nb_elem; n++) | for (n=0; n < matroska->tracks.nb_elem; n++) | ||||
| if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) | if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) | ||||
| av_free(tracks[n].audio.buf); | av_free(tracks[n].audio.buf); | ||||
| ebml_free(matroska_cluster, &matroska->current_cluster); | |||||
| ebml_free(matroska_segment, matroska); | ebml_free(matroska_segment, matroska); | ||||
| return 0; | return 0; | ||||
| @@ -133,8 +133,10 @@ int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, | |||||
| return AVERROR(EINVAL); | return AVERROR(EINVAL); | ||||
| /* auto-select alignment if not specified */ | /* auto-select alignment if not specified */ | ||||
| if (!align) | |||||
| align = 32; | |||||
| if (!align) { | |||||
| align = 1; | |||||
| nb_samples = FFALIGN(nb_samples, 32); | |||||
| } | |||||
| /* check for integer overflow */ | /* check for integer overflow */ | ||||
| if (nb_channels > INT_MAX / align || | if (nb_channels > INT_MAX / align || | ||||
| @@ -30,7 +30,7 @@ ret: 0 st: 0 flags:1 ts: 2.413000 | |||||
| ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292193 size: 27834 | ret: 0 st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos: 292193 size: 27834 | ||||
| ret:-1 st: 1 flags:0 ts: 1.307000 | ret:-1 st: 1 flags:0 ts: 1.307000 | ||||
| ret: 0 st: 1 flags:1 ts: 0.201000 | ret: 0 st: 1 flags:1 ts: 0.201000 | ||||
| ret: 0 st: 1 flags:1 dts: 0.198000 pts: 0.198000 pos: 555 size: 208 | |||||
| ret: 0 st: 1 flags:1 dts: 0.015000 pts: 0.015000 pos: 555 size: 208 | |||||
| ret: 0 st:-1 flags:0 ts:-0.904994 | ret: 0 st:-1 flags:0 ts:-0.904994 | ||||
| ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 555 size: 208 | ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 555 size: 208 | ||||
| ret: 0 st:-1 flags:1 ts: 1.989173 | ret: 0 st:-1 flags:1 ts: 1.989173 | ||||