From 1d3a9e63e0dcbcba633d939cdfb79e977259be13 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 23 Jan 2012 20:57:04 +0100 Subject: [PATCH 01/23] rv10: verify slice offsets against buffer size Found by John Villamil in fuzzed rv20 in mkv files. --- libavcodec/rv10.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index 1d78c92c46..9f2fe77af7 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -647,9 +647,12 @@ static int rv10_decode_frame(AVCodecContext *avctx, slice_count = avctx->slice_count; for(i=0; i= buf_size) + return AVERROR_INVALIDDATA; + if(i+1 == slice_count) size= buf_size - offset; else @@ -660,6 +663,10 @@ static int rv10_decode_frame(AVCodecContext *avctx, else size2= get_slice_offset(avctx, slices_hdr, i+2) - offset; + if (size <= 0 || size2 <= 0 || + offset + FFMAX(size, size2) > buf_size) + return AVERROR_INVALIDDATA; + if(rv10_decode_packet(avctx, buf+offset, size, size2) > 8*size) i++; } From d1ad6bdb6b578919f706694656a071d7ff7d9d84 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 23 Jan 2012 23:28:50 +0000 Subject: [PATCH 02/23] Changelog: restore version header Signed-off-by: Ronald S. Bultje --- Changelog | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Changelog b/Changelog index ae092b1f50..3bbbb14346 100644 --- a/Changelog +++ b/Changelog @@ -1,12 +1,15 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version : + +- XWD encoder and decoder + version 0.8: - GSM audio parser - SMJPEG muxer -- XWD encoder and decoder version 0.8_beta2: From 941e9f22386e923183dc4c5392d0ef2a85b68d51 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 Jan 2012 11:22:59 +0100 Subject: [PATCH 03/23] lavd: remove deprecated v4l grab device. --- configure | 2 - libavdevice/Makefile | 1 - libavdevice/alldevices.c | 3 - libavdevice/avdevice.h | 4 - libavdevice/v4l.c | 366 --------------------------------------- 5 files changed, 376 deletions(-) delete mode 100644 libavdevice/v4l.c diff --git a/configure b/configure index aff889457e..1c96393a36 100755 --- a/configure +++ b/configure @@ -1486,7 +1486,6 @@ oss_outdev_deps_any="soundcard_h sys_soundcard_h" pulse_indev_deps="libpulse" sndio_indev_deps="sndio_h" sndio_outdev_deps="sndio_h" -v4l_indev_deps="linux_videodev_h" v4l2_indev_deps_any="linux_videodev2_h sys_videoio_h" vfwcap_indev_deps="capCreateCaptureWindow vfwcap_defines" vfwcap_indev_extralibs="-lavicap32" @@ -2988,7 +2987,6 @@ fi texi2html -version > /dev/null 2>&1 && enable texi2html || disable texi2html check_header linux/fb.h -check_header linux/videodev.h check_header linux/videodev2.h check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 1a1e2f129d..82268172c3 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -20,7 +20,6 @@ OBJS-$(CONFIG_PULSE_INDEV) += pulse.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio_common.o sndio_dec.o OBJS-$(CONFIG_SNDIO_OUTDEV) += sndio_common.o sndio_enc.o OBJS-$(CONFIG_V4L2_INDEV) += v4l2.o -OBJS-$(CONFIG_V4L_INDEV) += v4l.o OBJS-$(CONFIG_VFWCAP_INDEV) += vfwcap.o OBJS-$(CONFIG_X11_GRAB_DEVICE_INDEV) += x11grab.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index e65644bc1a..f1ff79046c 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -48,9 +48,6 @@ void avdevice_register_all(void) REGISTER_INDEV (PULSE, pulse); REGISTER_INOUTDEV (SNDIO, sndio); REGISTER_INDEV (V4L2, v4l2); -#if FF_API_V4L - REGISTER_INDEV (V4L, v4l); -#endif REGISTER_INDEV (VFWCAP, vfwcap); REGISTER_INDEV (X11_GRAB_DEVICE, x11_grab_device); diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index e6c86cb3c3..553604137c 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -55,10 +55,6 @@ LIBAVDEVICE_VERSION_MICRO) #define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT -#ifndef FF_API_V4L -#define FF_API_V4L (LIBAVDEVICE_VERSION_MAJOR < 54) -#endif - /** * Return the LIBAVDEVICE_VERSION_INT constant. */ diff --git a/libavdevice/v4l.c b/libavdevice/v4l.c deleted file mode 100644 index bdfee2df4e..0000000000 --- a/libavdevice/v4l.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Linux video grab interface - * Copyright (c) 2000,2001 Fabrice Bellard - * - * This file is part of Libav. - * - * Libav 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. - * - * Libav 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 Libav; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "avdevice.h" - -#if FF_API_V4L - -#undef __STRICT_ANSI__ //workaround due to broken kernel headers -#include "config.h" -#include "libavutil/rational.h" -#include "libavutil/imgutils.h" -#include "libavutil/log.h" -#include "libavutil/opt.h" -#include "libavformat/avformat.h" -#include "libavformat/internal.h" -#include "libavcodec/dsputil.h" -#include -#include -#include -#include -#include -#define _LINUX_TIME_H 1 -#include -#include - -typedef struct { - AVClass *class; - int fd; - int frame_format; /* see VIDEO_PALETTE_xxx */ - int use_mmap; - AVRational time_base; - int64_t time_frame; - int frame_size; - struct video_capability video_cap; - struct video_audio audio_saved; - struct video_window video_win; - uint8_t *video_buf; - struct video_mbuf gb_buffers; - struct video_mmap gb_buf; - int gb_frame; - int standard; -} VideoData; - -static const struct { - int palette; - int depth; - enum PixelFormat pix_fmt; -} video_formats [] = { - {.palette = VIDEO_PALETTE_YUV420P, .depth = 12, .pix_fmt = PIX_FMT_YUV420P }, - {.palette = VIDEO_PALETTE_YUV422, .depth = 16, .pix_fmt = PIX_FMT_YUYV422 }, - {.palette = VIDEO_PALETTE_UYVY, .depth = 16, .pix_fmt = PIX_FMT_UYVY422 }, - {.palette = VIDEO_PALETTE_YUYV, .depth = 16, .pix_fmt = PIX_FMT_YUYV422 }, - /* NOTE: v4l uses BGR24, not RGB24 */ - {.palette = VIDEO_PALETTE_RGB24, .depth = 24, .pix_fmt = PIX_FMT_BGR24 }, - {.palette = VIDEO_PALETTE_RGB565, .depth = 16, .pix_fmt = PIX_FMT_BGR565 }, - {.palette = VIDEO_PALETTE_GREY, .depth = 8, .pix_fmt = PIX_FMT_GRAY8 }, -}; - - -static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) -{ - VideoData *s = s1->priv_data; - AVStream *st; - int video_fd; - int desired_palette, desired_depth; - struct video_tuner tuner; - struct video_audio audio; - struct video_picture pict; - int j; - int vformat_num = FF_ARRAY_ELEMS(video_formats); - - av_log(s1, AV_LOG_WARNING, "V4L input device is deprecated and will be removed in the next release."); - - if (ap->time_base.den <= 0) { - av_log(s1, AV_LOG_ERROR, "Wrong time base (%d)\n", ap->time_base.den); - return -1; - } - s->time_base = ap->time_base; - - s->video_win.width = ap->width; - s->video_win.height = ap->height; - - st = avformat_new_stream(s1, NULL); - if (!st) - return AVERROR(ENOMEM); - avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - - video_fd = open(s1->filename, O_RDWR); - if (video_fd < 0) { - av_log(s1, AV_LOG_ERROR, "%s: %s\n", s1->filename, strerror(errno)); - goto fail; - } - - if (ioctl(video_fd, VIDIOCGCAP, &s->video_cap) < 0) { - av_log(s1, AV_LOG_ERROR, "VIDIOCGCAP: %s\n", strerror(errno)); - goto fail; - } - - if (!(s->video_cap.type & VID_TYPE_CAPTURE)) { - av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n"); - goto fail; - } - - /* no values set, autodetect them */ - if (s->video_win.width <= 0 || s->video_win.height <= 0) { - if (ioctl(video_fd, VIDIOCGWIN, &s->video_win, sizeof(s->video_win)) < 0) { - av_log(s1, AV_LOG_ERROR, "VIDIOCGWIN: %s\n", strerror(errno)); - goto fail; - } - } - - if(av_image_check_size(s->video_win.width, s->video_win.height, 0, s1) < 0) - return -1; - - desired_palette = -1; - desired_depth = -1; - for (j = 0; j < vformat_num; j++) { - if (ap->pix_fmt == video_formats[j].pix_fmt) { - desired_palette = video_formats[j].palette; - desired_depth = video_formats[j].depth; - break; - } - } - - /* set tv standard */ - if (!ioctl(video_fd, VIDIOCGTUNER, &tuner)) { - tuner.mode = s->standard; - ioctl(video_fd, VIDIOCSTUNER, &tuner); - } - - /* unmute audio */ - audio.audio = 0; - ioctl(video_fd, VIDIOCGAUDIO, &audio); - memcpy(&s->audio_saved, &audio, sizeof(audio)); - audio.flags &= ~VIDEO_AUDIO_MUTE; - ioctl(video_fd, VIDIOCSAUDIO, &audio); - - ioctl(video_fd, VIDIOCGPICT, &pict); - av_dlog(s1, "v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n", - pict.colour, pict.hue, pict.brightness, pict.contrast, pict.whiteness); - /* try to choose a suitable video format */ - pict.palette = desired_palette; - pict.depth= desired_depth; - if (desired_palette == -1 || ioctl(video_fd, VIDIOCSPICT, &pict) < 0) { - for (j = 0; j < vformat_num; j++) { - pict.palette = video_formats[j].palette; - pict.depth = video_formats[j].depth; - if (-1 != ioctl(video_fd, VIDIOCSPICT, &pict)) - break; - } - if (j >= vformat_num) - goto fail1; - } - - if (ioctl(video_fd, VIDIOCGMBUF, &s->gb_buffers) < 0) { - /* try to use read based access */ - int val; - - s->video_win.x = 0; - s->video_win.y = 0; - s->video_win.chromakey = -1; - s->video_win.flags = 0; - - if (ioctl(video_fd, VIDIOCSWIN, s->video_win) < 0) { - av_log(s1, AV_LOG_ERROR, "VIDIOCSWIN: %s\n", strerror(errno)); - goto fail; - } - - s->frame_format = pict.palette; - - val = 1; - if (ioctl(video_fd, VIDIOCCAPTURE, &val) < 0) { - av_log(s1, AV_LOG_ERROR, "VIDIOCCAPTURE: %s\n", strerror(errno)); - goto fail; - } - - s->time_frame = av_gettime() * s->time_base.den / s->time_base.num; - s->use_mmap = 0; - } else { - s->video_buf = mmap(0, s->gb_buffers.size, PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, 0); - if ((unsigned char*)-1 == s->video_buf) { - s->video_buf = mmap(0, s->gb_buffers.size, PROT_READ|PROT_WRITE, MAP_PRIVATE, video_fd, 0); - if ((unsigned char*)-1 == s->video_buf) { - av_log(s1, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); - goto fail; - } - } - s->gb_frame = 0; - s->time_frame = av_gettime() * s->time_base.den / s->time_base.num; - - /* start to grab the first frame */ - s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames; - s->gb_buf.height = s->video_win.height; - s->gb_buf.width = s->video_win.width; - s->gb_buf.format = pict.palette; - - if (ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) { - if (errno != EAGAIN) { - fail1: - av_log(s1, AV_LOG_ERROR, "VIDIOCMCAPTURE: %s\n", strerror(errno)); - } else { - av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not receive any video signal\n"); - } - goto fail; - } - for (j = 1; j < s->gb_buffers.frames; j++) { - s->gb_buf.frame = j; - ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf); - } - s->frame_format = s->gb_buf.format; - s->use_mmap = 1; - } - - for (j = 0; j < vformat_num; j++) { - if (s->frame_format == video_formats[j].palette) { - s->frame_size = s->video_win.width * s->video_win.height * video_formats[j].depth / 8; - st->codec->pix_fmt = video_formats[j].pix_fmt; - break; - } - } - - if (j >= vformat_num) - goto fail; - - s->fd = video_fd; - - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = CODEC_ID_RAWVIDEO; - st->codec->width = s->video_win.width; - st->codec->height = s->video_win.height; - st->codec->time_base = s->time_base; - st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8; - - return 0; - fail: - if (video_fd >= 0) - close(video_fd); - return AVERROR(EIO); -} - -static int v4l_mm_read_picture(VideoData *s, uint8_t *buf) -{ - uint8_t *ptr; - - while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 && - (errno == EAGAIN || errno == EINTR)); - - ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame]; - memcpy(buf, ptr, s->frame_size); - - /* Setup to capture the next frame */ - s->gb_buf.frame = s->gb_frame; - if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) { - if (errno == EAGAIN) - av_log(NULL, AV_LOG_ERROR, "Cannot Sync\n"); - else - av_log(NULL, AV_LOG_ERROR, "VIDIOCMCAPTURE: %s\n", strerror(errno)); - return AVERROR(EIO); - } - - /* This is now the grabbing frame */ - s->gb_frame = (s->gb_frame + 1) % s->gb_buffers.frames; - - return s->frame_size; -} - -static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt) -{ - VideoData *s = s1->priv_data; - int64_t curtime, delay; - struct timespec ts; - - /* Calculate the time of the next frame */ - s->time_frame += INT64_C(1000000); - - /* wait based on the frame rate */ - for(;;) { - curtime = av_gettime(); - delay = s->time_frame * s->time_base.num / s->time_base.den - curtime; - if (delay <= 0) { - if (delay < INT64_C(-1000000) * s->time_base.num / s->time_base.den) { - /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */ - s->time_frame += INT64_C(1000000); - } - break; - } - ts.tv_sec = delay / 1000000; - ts.tv_nsec = (delay % 1000000) * 1000; - nanosleep(&ts, NULL); - } - - if (av_new_packet(pkt, s->frame_size) < 0) - return AVERROR(EIO); - - pkt->pts = curtime; - - /* read one frame */ - if (s->use_mmap) { - return v4l_mm_read_picture(s, pkt->data); - } else { - if (read(s->fd, pkt->data, pkt->size) != pkt->size) - return AVERROR(EIO); - return s->frame_size; - } -} - -static int grab_read_close(AVFormatContext *s1) -{ - VideoData *s = s1->priv_data; - - if (s->use_mmap) - munmap(s->video_buf, s->gb_buffers.size); - - /* mute audio. we must force it because the BTTV driver does not - return its state correctly */ - s->audio_saved.flags |= VIDEO_AUDIO_MUTE; - ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved); - - close(s->fd); - return 0; -} - -static const AVOption options[] = { - { "standard", "", offsetof(VideoData, standard), AV_OPT_TYPE_INT, {.dbl = VIDEO_MODE_NTSC}, VIDEO_MODE_PAL, VIDEO_MODE_NTSC, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "PAL", "", 0, AV_OPT_TYPE_CONST, {.dbl = VIDEO_MODE_PAL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "SECAM", "", 0, AV_OPT_TYPE_CONST, {.dbl = VIDEO_MODE_SECAM}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { "NTSC", "", 0, AV_OPT_TYPE_CONST, {.dbl = VIDEO_MODE_NTSC}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" }, - { NULL }, -}; - -static const AVClass v4l_class = { - .class_name = "V4L indev", - .item_name = av_default_item_name, - .option = options, - .version = LIBAVUTIL_VERSION_INT, -}; - -AVInputFormat ff_v4l_demuxer = { - .name = "video4linux", - .long_name = NULL_IF_CONFIG_SMALL("Video4Linux device grab"), - .priv_data_size = sizeof(VideoData), - .read_header = grab_read_header, - .read_packet = grab_read_packet, - .read_close = grab_read_close, - .flags = AVFMT_NOFILE, - .priv_class = &v4l_class, -}; -#endif /* FF_API_V4L */ From 75e2025f57fef5060d74c65d9654e61c35bd6c81 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 22 Jan 2012 10:51:26 +0100 Subject: [PATCH 04/23] avplay: remove the -er option. Error recognition flags can and should be set directly with AVOptions. --- avplay.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/avplay.c b/avplay.c index 432afc11b3..27ac01ae33 100644 --- a/avplay.c +++ b/avplay.c @@ -251,7 +251,6 @@ static int idct = FF_IDCT_AUTO; static enum AVDiscard skip_frame = AVDISCARD_DEFAULT; static enum AVDiscard skip_idct = AVDISCARD_DEFAULT; static enum AVDiscard skip_loop_filter = AVDISCARD_DEFAULT; -static int error_recognition = FF_ER_CAREFUL; static int error_concealment = 3; static int decoder_reorder_pts = -1; static int autoexit; @@ -2187,7 +2186,6 @@ static int stream_component_open(VideoState *is, int stream_index) avctx->skip_frame = skip_frame; avctx->skip_idct = skip_idct; avctx->skip_loop_filter = skip_loop_filter; - avctx->error_recognition = error_recognition; avctx->error_concealment = error_concealment; avctx->thread_count = thread_count; @@ -2992,7 +2990,6 @@ static const OptionDef options[] = { { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_frame }, "", "" }, { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_idct }, "", "" }, { "idct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&idct }, "set idct algo", "algo" }, - { "er", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&error_recognition }, "set error detection threshold (0-4)", "threshold" }, { "ec", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&error_concealment }, "set error concealment options", "bit_mask" }, { "sync", HAS_ARG | OPT_EXPERT, { (void*)opt_sync }, "set audio-video sync. type (type=audio/video/ext)", "type" }, { "threads", HAS_ARG | OPT_EXPERT, { (void*)opt_thread_count }, "thread count", "count" }, From af0292f33a7d9a024a10a05748415622ea45e08e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 22 Jan 2012 10:43:40 +0100 Subject: [PATCH 05/23] lavc: postpone removing old audio encoding and decoding API It has been deprecated only recently. --- libavcodec/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 77e16823f9..1de790e3d9 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -114,13 +114,13 @@ #define FF_API_DATA_POINTERS (LIBAVCODEC_VERSION_MAJOR < 54) #endif #ifndef FF_API_OLD_DECODE_AUDIO -#define FF_API_OLD_DECODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 54) +#define FF_API_OLD_DECODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) #endif #ifndef FF_API_AVFRAME_AGE #define FF_API_AVFRAME_AGE (LIBAVCODEC_VERSION_MAJOR < 54) #endif #ifndef FF_API_OLD_ENCODE_AUDIO -#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 54) +#define FF_API_OLD_ENCODE_AUDIO (LIBAVCODEC_VERSION_MAJOR < 55) #endif #endif /* AVCODEC_VERSION_H */ From dc7ad30fa5b3d454a3edcc3b051aef3a65c5235b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 22 Jan 2012 10:43:40 +0100 Subject: [PATCH 06/23] lavf: postpone removing av_close_input_file(). It has been deprecated only recently. --- libavformat/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/version.h b/libavformat/version.h index cd774fbe65..d50b2a54dc 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -120,7 +120,7 @@ #define FF_API_SET_PTS_INFO (LIBAVFORMAT_VERSION_MAJOR < 54) #endif #ifndef FF_API_CLOSE_INPUT_FILE -#define FF_API_CLOSE_INPUT_FILE (LIBAVFORMAT_VERSION_MAJOR < 54) +#define FF_API_CLOSE_INPUT_FILE (LIBAVFORMAT_VERSION_MAJOR < 55) #endif #endif /* AVFORMAT_VERSION_H */ From 1381e9bc92e54f0c3472a1f7150a8530ccd55379 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 Jan 2012 11:16:38 +0100 Subject: [PATCH 07/23] lavc: postpone the removal of AVCodecContext.request_channels. Although it has been deprecated for a long time, its intended replacement (request_channel_layout) is not actually used anywhere, so request_channels is currently the only way to access that functionality. --- libavcodec/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/version.h b/libavcodec/version.h index 1de790e3d9..22a2b87798 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -51,7 +51,7 @@ #define FF_API_ANTIALIAS_ALGO (LIBAVCODEC_VERSION_MAJOR < 54) #endif #ifndef FF_API_REQUEST_CHANNELS -#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 54) +#define FF_API_REQUEST_CHANNELS (LIBAVCODEC_VERSION_MAJOR < 55) #endif #ifndef FF_API_OPT_H #define FF_API_OPT_H (LIBAVCODEC_VERSION_MAJOR < 54) From e1ac69fa27b924999bc5dbb7ffefa2af88bf3798 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 10:52:49 -0500 Subject: [PATCH 08/23] vqa: set stream start_time to 0. The format has no coded timestamps and must use packet durations to generate them. --- libavformat/westwood_vqa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 2eff4cc0a5..20462d99c2 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -94,6 +94,7 @@ static int wsvqa_read_header(AVFormatContext *s, st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); + st->start_time = 0; avpriv_set_pts_info(st, 33, 1, VQA_FRAMERATE); wsvqa->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; @@ -120,6 +121,7 @@ static int wsvqa_read_header(AVFormatContext *s, st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); + st->start_time = 0; avpriv_set_pts_info(st, 33, 1, VQA_FRAMERATE); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (AV_RL16(&header[0]) == 1) From 53ed79a260099c761f8a74872d695a2aeb7a0ced Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 10:55:28 -0500 Subject: [PATCH 09/23] vqa: use 1/sample_rate as the audio stream time base --- libavformat/westwood_vqa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 20462d99c2..fef6877944 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -122,7 +122,6 @@ static int wsvqa_read_header(AVFormatContext *s, if (!st) return AVERROR(ENOMEM); st->start_time = 0; - avpriv_set_pts_info(st, 33, 1, VQA_FRAMERATE); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; if (AV_RL16(&header[0]) == 1) st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; @@ -140,6 +139,8 @@ static int wsvqa_read_header(AVFormatContext *s, st->codec->bits_per_coded_sample / 4; st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + wsvqa->audio_stream_index = st->index; wsvqa->audio_samplerate = st->codec->sample_rate; wsvqa->audio_channels = st->codec->channels; From 9ae846971fc1dd1dff5cac9b8f26cff499e053c5 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 11:06:35 -0500 Subject: [PATCH 10/23] vqa: set packet duration. Also remove unused context field, audio_frame_counter. --- libavformat/westwood_vqa.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index fef6877944..9a4826340c 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -61,8 +61,6 @@ typedef struct WsVqaDemuxContext { int audio_stream_index; int video_stream_index; - - int64_t audio_frame_counter; } WsVqaDemuxContext; static int wsvqa_probe(AVProbeData *p) @@ -144,7 +142,6 @@ static int wsvqa_read_header(AVFormatContext *s, wsvqa->audio_stream_index = st->index; wsvqa->audio_samplerate = st->codec->sample_rate; wsvqa->audio_channels = st->codec->channels; - wsvqa->audio_frame_counter = 0; } /* there are 0 or more chunks before the FINF chunk; iterate until @@ -216,13 +213,14 @@ static int wsvqa_read_packet(AVFormatContext *s, if (chunk_type == SND2_TAG) { pkt->stream_index = wsvqa->audio_stream_index; /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ - wsvqa->audio_frame_counter += (chunk_size * 2) / wsvqa->audio_channels; + pkt->duration = (chunk_size * 2) / wsvqa->audio_channels; } else if(chunk_type == SND1_TAG) { pkt->stream_index = wsvqa->audio_stream_index; /* unpacked size is stored in header */ - wsvqa->audio_frame_counter += AV_RL16(pkt->data) / wsvqa->audio_channels; + pkt->duration = AV_RL16(pkt->data) / wsvqa->audio_channels; } else { pkt->stream_index = wsvqa->video_stream_index; + pkt->duration = 1; } /* stay on 16-bit alignment */ if (skip_byte) From 5b4c5628973d212ecaa1aabaeebd0205738ceddd Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 11:38:00 -0500 Subject: [PATCH 11/23] vqa: set time base to frame rate as coded in the header. According to Multimedia Wiki documentation, the frame rate is not always 15, and the actual value can be found in the header. --- libavformat/westwood_vqa.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 9a4826340c..a99a816062 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -51,7 +51,6 @@ #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S') #define VQA_HEADER_SIZE 0x2A -#define VQA_FRAMERATE 15 #define VQA_PREAMBLE_SIZE 8 typedef struct WsVqaDemuxContext { @@ -87,13 +86,13 @@ static int wsvqa_read_header(AVFormatContext *s, unsigned char scratch[VQA_PREAMBLE_SIZE]; unsigned int chunk_tag; unsigned int chunk_size; + int fps; /* initialize the video decoder stream */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->start_time = 0; - avpriv_set_pts_info(st, 33, 1, VQA_FRAMERATE); wsvqa->video_stream_index = st->index; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_WS_VQA; @@ -113,6 +112,12 @@ static int wsvqa_read_header(AVFormatContext *s, } st->codec->width = AV_RL16(&header[6]); st->codec->height = AV_RL16(&header[8]); + fps = header[12]; + if (fps < 1 || fps > 30) { + av_log(s, AV_LOG_ERROR, "invalid fps: %d\n", fps); + return AVERROR_INVALIDDATA; + } + avpriv_set_pts_info(st, 64, 1, fps); /* initialize the audio decoder stream for VQA v1 or nonzero samplerate */ if (AV_RL16(&header[24]) || (AV_RL16(&header[0]) == 1 && AV_RL16(&header[2]) == 1)) { From 7e813d59335753ab07be82919f36ddcaf075463a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 13:28:20 -0500 Subject: [PATCH 12/23] vqa: clean up audio header parsing Fix setting of bit_rate and bits_per_coded_sample. Ask for sample for unsupported VQA versions. --- libavformat/westwood_vqa.c | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index a99a816062..c338d95182 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -86,7 +86,7 @@ static int wsvqa_read_header(AVFormatContext *s, unsigned char scratch[VQA_PREAMBLE_SIZE]; unsigned int chunk_tag; unsigned int chunk_size; - int fps; + int fps, version, flags, sample_rate, channels; /* initialize the video decoder stream */ st = avformat_new_stream(s, NULL); @@ -120,30 +120,43 @@ static int wsvqa_read_header(AVFormatContext *s, avpriv_set_pts_info(st, 64, 1, fps); /* initialize the audio decoder stream for VQA v1 or nonzero samplerate */ - if (AV_RL16(&header[24]) || (AV_RL16(&header[0]) == 1 && AV_RL16(&header[2]) == 1)) { + version = AV_RL16(&header[ 0]); + flags = AV_RL16(&header[ 2]); + sample_rate = AV_RL16(&header[24]); + channels = header[26]; + if (sample_rate || (version == 1 && flags == 1)) { st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); st->start_time = 0; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - if (AV_RL16(&header[0]) == 1) - st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; - else - st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; - st->codec->codec_tag = 0; /* no tag */ - st->codec->sample_rate = AV_RL16(&header[24]); - if (!st->codec->sample_rate) - st->codec->sample_rate = 22050; - st->codec->channels = header[26]; - if (!st->codec->channels) - st->codec->channels = 1; - st->codec->bits_per_coded_sample = 16; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample / 4; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + if (!sample_rate) + sample_rate = 22050; + st->codec->sample_rate = sample_rate; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + if (!channels) + channels = 1; + st->codec->channels = channels; + + switch (version) { + case 1: + st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; + break; + case 2: + case 3: + st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; + st->codec->bits_per_coded_sample = 4; + st->codec->bit_rate = channels * sample_rate * 4; + break; + default: + /* NOTE: version 0 is supposedly raw pcm_u8 or pcm_s16le, but we do + not have any samples to validate this */ + av_log_ask_for_sample(s, "VQA version %d audio\n", version); + return AVERROR_PATCHWELCOME; + } + wsvqa->audio_stream_index = st->index; wsvqa->audio_samplerate = st->codec->sample_rate; wsvqa->audio_channels = st->codec->channels; From 4340a6363e9ff75dc4e8ce14dc96671623494ed8 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 13:43:54 -0500 Subject: [PATCH 13/23] vqa: remove unused context fields, audio_samplerate and audio_bits --- libavformat/westwood_vqa.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index c338d95182..4d6397b88c 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -54,10 +54,7 @@ #define VQA_PREAMBLE_SIZE 8 typedef struct WsVqaDemuxContext { - int audio_samplerate; int audio_channels; - int audio_bits; - int audio_stream_index; int video_stream_index; } WsVqaDemuxContext; @@ -158,7 +155,6 @@ static int wsvqa_read_header(AVFormatContext *s, } wsvqa->audio_stream_index = st->index; - wsvqa->audio_samplerate = st->codec->sample_rate; wsvqa->audio_channels = st->codec->channels; } From 220506d23f39da3e23d3d42fb7061f19cec8052c Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 14:57:32 -0500 Subject: [PATCH 14/23] avcodec: add a new codec_id for CRYO APC IMA ADPCM. The stereo layout and extradata is significantly different from that in Westwood IMA ADPCM, so a separate codec_id is warranted. --- libavcodec/Makefile | 1 + libavcodec/adpcm.c | 7 +++++-- libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/utils.c | 1 + libavcodec/version.h | 2 +- libavformat/apc.c | 2 +- libavformat/yop.c | 2 +- 8 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3468f66863..620c99e980 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -509,6 +509,7 @@ OBJS-$(CONFIG_ADPCM_G722_ENCODER) += g722.o g722enc.o OBJS-$(CONFIG_ADPCM_G726_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o adpcm_data.o diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index b319635ed4..64bea6a5da 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -120,8 +120,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) return -1; } break; - case CODEC_ID_ADPCM_IMA_WS: - if (avctx->extradata && avctx->extradata_size == 2 * 4) { + case CODEC_ID_ADPCM_IMA_APC: + if (avctx->extradata && avctx->extradata_size >= 8) { c->status[0].predictor = AV_RL32(avctx->extradata); c->status[1].predictor = AV_RL32(avctx->extradata + 4); } @@ -359,6 +359,7 @@ static int get_nb_samples(AVCodecContext *avctx, const uint8_t *buf, break; /* simple 4-bit adpcm */ case CODEC_ID_ADPCM_CT: + case CODEC_ID_ADPCM_IMA_APC: case CODEC_ID_ADPCM_IMA_EA_SEAD: case CODEC_ID_ADPCM_IMA_WS: case CODEC_ID_ADPCM_YAMAHA: @@ -774,6 +775,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } break; case CODEC_ID_ADPCM_IMA_WS: + case CODEC_ID_ADPCM_IMA_APC: while (src < buf + buf_size) { uint8_t v = *src++; *samples++ = adpcm_ima_expand_nibble(&c->status[0], v >> 4 , 3); @@ -1220,6 +1222,7 @@ ADPCM_DECODER(CODEC_ID_ADPCM_EA_R2, adpcm_ea_r2, "ADPCM Electronic Arts R2"); ADPCM_DECODER(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3, "ADPCM Electronic Arts R3"); ADPCM_DECODER(CODEC_ID_ADPCM_EA_XAS, adpcm_ea_xas, "ADPCM Electronic Arts XAS"); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv, "ADPCM IMA AMV"); +ADPCM_DECODER(CODEC_ID_ADPCM_IMA_APC, adpcm_ima_apc, "ADPCM IMA CRYO APC"); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3, "ADPCM IMA Duck DK3"); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4, "ADPCM IMA Duck DK4"); ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS"); diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d00bd0b79c..fe1ee5c4b0 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -342,6 +342,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (ADPCM_G722, adpcm_g722); REGISTER_ENCDEC (ADPCM_G726, adpcm_g726); REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv); + REGISTER_DECODER (ADPCM_IMA_APC, adpcm_ima_apc); REGISTER_DECODER (ADPCM_IMA_DK3, adpcm_ima_dk3); REGISTER_DECODER (ADPCM_IMA_DK4, adpcm_ima_dk4); REGISTER_DECODER (ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 967a134bdd..1c2766316e 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -317,6 +317,7 @@ enum CodecID { CODEC_ID_ADPCM_EA_MAXIS_XA, CODEC_ID_ADPCM_IMA_ISS, CODEC_ID_ADPCM_G722, + CODEC_ID_ADPCM_IMA_APC, /* AMR */ CODEC_ID_AMR_NB = 0x12000, diff --git a/libavcodec/utils.c b/libavcodec/utils.c index ff3f065064..184f67e566 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -1617,6 +1617,7 @@ int av_get_bits_per_sample(enum CodecID codec_id){ return 3; case CODEC_ID_ADPCM_SBPRO_4: case CODEC_ID_ADPCM_CT: + case CODEC_ID_ADPCM_IMA_APC: case CODEC_ID_ADPCM_IMA_WAV: case CODEC_ID_ADPCM_IMA_QT: case CODEC_ID_ADPCM_SWF: diff --git a/libavcodec/version.h b/libavcodec/version.h index 22a2b87798..95d0baa612 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 35 +#define LIBAVCODEC_VERSION_MINOR 36 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/apc.c b/libavformat/apc.c index 238395087c..47ab5c821b 100644 --- a/libavformat/apc.c +++ b/libavformat/apc.c @@ -44,7 +44,7 @@ static int apc_read_header(AVFormatContext *s, AVFormatParameters *ap) return AVERROR(ENOMEM); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; + st->codec->codec_id = CODEC_ID_ADPCM_IMA_APC; avio_rl32(pb); /* number of samples */ st->codec->sample_rate = avio_rl32(pb); diff --git a/libavformat/yop.c b/libavformat/yop.c index a317825a7c..e5ace8b805 100644 --- a/libavformat/yop.c +++ b/libavformat/yop.c @@ -72,7 +72,7 @@ static int yop_read_header(AVFormatContext *s, AVFormatParameters *ap) // Audio audio_dec = audio_stream->codec; audio_dec->codec_type = AVMEDIA_TYPE_AUDIO; - audio_dec->codec_id = CODEC_ID_ADPCM_IMA_WS; + audio_dec->codec_id = CODEC_ID_ADPCM_IMA_APC; audio_dec->channels = 1; audio_dec->sample_rate = 22050; From 02e7dbf5adc6aa702472010c33aec9bfd904702f Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 23 Jan 2012 12:23:27 -0500 Subject: [PATCH 15/23] adpcm_ima_ws: fix stereo decoding Stereo ADPCM IMA WS is planar for VQA version 3 and 2-sample interleaved for VQA version 2. --- libavcodec/adpcm.c | 30 +++++++++++++++++++++++++++++- libavformat/westwood_vqa.c | 6 ++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 64bea6a5da..bd86ab0e61 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -86,6 +86,7 @@ static const int swf_index_tables[4][16] = { typedef struct ADPCMDecodeContext { AVFrame frame; ADPCMChannelStatus status[6]; + int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */ } ADPCMDecodeContext; static av_cold int adpcm_decode_init(AVCodecContext * avctx) @@ -126,6 +127,10 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) c->status[1].predictor = AV_RL32(avctx->extradata + 4); } break; + case CODEC_ID_ADPCM_IMA_WS: + if (avctx->extradata && avctx->extradata_size >= 42) + c->vqa_version = AV_RL16(avctx->extradata); + break; default: break; } @@ -774,7 +779,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3); } break; - case CODEC_ID_ADPCM_IMA_WS: case CODEC_ID_ADPCM_IMA_APC: while (src < buf + buf_size) { uint8_t v = *src++; @@ -782,6 +786,30 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, *samples++ = adpcm_ima_expand_nibble(&c->status[st], v & 0x0F, 3); } break; + case CODEC_ID_ADPCM_IMA_WS: + for (channel = 0; channel < avctx->channels; channel++) { + const uint8_t *src0; + int src_stride; + int16_t *smp = samples + channel; + + if (c->vqa_version == 3) { + src0 = src + channel * buf_size / 2; + src_stride = 1; + } else { + src0 = src + channel; + src_stride = avctx->channels; + } + for (n = nb_samples / 2; n > 0; n--) { + uint8_t v = *src0; + src0 += src_stride; + *smp = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); + smp += avctx->channels; + *smp = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); + smp += avctx->channels; + } + } + src = buf + buf_size; + break; case CODEC_ID_ADPCM_XA: while (buf_size >= 128) { xa_decode(samples, src, &c->status[0], &c->status[1], diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 4d6397b88c..c2aebe5e80 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -128,6 +128,12 @@ static int wsvqa_read_header(AVFormatContext *s, st->start_time = 0; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->extradata_size = VQA_HEADER_SIZE; + st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); + memcpy(st->codec->extradata, header, VQA_HEADER_SIZE); + if (!sample_rate) sample_rate = 22050; st->codec->sample_rate = sample_rate; From d481227c549aece0bc4a05819a771806b6cd7507 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:09:05 -0500 Subject: [PATCH 16/23] aud: support Westwood SND1 audio in AUD files. Fixes decoding of the handful of "death scream" samples from "Command and Conquer" that use SND1. e.g. http://samples.libav.org/game-formats/westwood-aud/nuyell1.aud http://samples.libav.org/game-formats/westwood-aud/nuyell7.aud --- libavformat/westwood_aud.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index b1eb768016..652045f579 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -79,7 +79,7 @@ static int wsaud_probe(AVProbeData *p) /* note: only check for WS IMA (type 99) right now since there is no * support for type 1 */ - if (p->buf[11] != 99) + if (p->buf[11] != 99 && p->buf[11] != 1) return 0; /* read ahead to the first audio chunk and validate the first header signature */ @@ -103,6 +103,8 @@ static int wsaud_read_header(AVFormatContext *s, wsaud->audio_samplerate = AV_RL16(&header[0]); if (header[11] == 99) wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS; + else if (header[11] == 1) + wsaud->audio_type = CODEC_ID_WESTWOOD_SND1; else return AVERROR_INVALIDDATA; @@ -121,10 +123,10 @@ static int wsaud_read_header(AVFormatContext *s, st->codec->codec_tag = 0; /* no tag */ st->codec->channels = wsaud->audio_channels; st->codec->sample_rate = wsaud->audio_samplerate; - st->codec->bits_per_coded_sample = wsaud->audio_bits; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample / 4; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + if (st->codec->codec_id == CODEC_ID_ADPCM_IMA_WS) { + st->codec->bits_per_coded_sample = 4; + st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 4; + } wsaud->audio_stream_index = st->index; wsaud->audio_frame_counter = 0; @@ -140,6 +142,7 @@ static int wsaud_read_packet(AVFormatContext *s, unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE]; unsigned int chunk_size; int ret = 0; + AVStream *st = s->streams[wsaud->audio_stream_index]; if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != AUD_CHUNK_PREAMBLE_SIZE) @@ -150,15 +153,32 @@ static int wsaud_read_packet(AVFormatContext *s, return AVERROR_INVALIDDATA; chunk_size = AV_RL16(&preamble[0]); + + if (st->codec->codec_id == CODEC_ID_WESTWOOD_SND1) { + /* For Westwood SND1 audio we need to add the output size and input + size to the start of the packet to match what is in VQA. + Specifically, this is needed to signal when a packet should be + decoding as raw 8-bit pcm or variable-size ADPCM. */ + int out_size = AV_RL16(&preamble[2]); + if ((ret = av_new_packet(pkt, chunk_size + 4))) + return ret; + if ((ret = avio_read(pb, &pkt->data[4], chunk_size)) != chunk_size) + return ret < 0 ? ret : AVERROR(EIO); + AV_WL16(&pkt->data[0], out_size); + AV_WL16(&pkt->data[2], chunk_size); + + pkt->duration = out_size; + } else { ret= av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR(EIO); - pkt->stream_index = wsaud->audio_stream_index; pkt->pts = wsaud->audio_frame_counter; pkt->pts /= wsaud->audio_samplerate; /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels; + } + pkt->stream_index = st->index; return ret; } From 98c290cc0828a25b04259f2b408054aaeca016e4 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:41:37 -0500 Subject: [PATCH 17/23] cosmetics: indentation --- libavformat/westwood_aud.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 652045f579..21d16f7385 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -169,14 +169,14 @@ static int wsaud_read_packet(AVFormatContext *s, pkt->duration = out_size; } else { - ret= av_get_packet(pb, pkt, chunk_size); - if (ret != chunk_size) - return AVERROR(EIO); - pkt->pts = wsaud->audio_frame_counter; - pkt->pts /= wsaud->audio_samplerate; + ret = av_get_packet(pb, pkt, chunk_size); + if (ret != chunk_size) + return AVERROR(EIO); + pkt->pts = wsaud->audio_frame_counter; + pkt->pts /= wsaud->audio_samplerate; - /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ - wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels; + /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ + wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels; } pkt->stream_index = st->index; From 0e6a8b5cf76f830923c85730e6369ca46cfe834c Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:28:02 -0500 Subject: [PATCH 18/23] aud: set pts_wrap_bits to 64. Time stamps are not read from the bitstream, so no wrapping is needed. --- libavformat/westwood_aud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 21d16f7385..27dc3fae63 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -117,7 +117,7 @@ static int wsaud_read_header(AVFormatContext *s, st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - avpriv_set_pts_info(st, 33, 1, wsaud->audio_samplerate); + avpriv_set_pts_info(st, 64, 1, wsaud->audio_samplerate); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = wsaud->audio_type; st->codec->codec_tag = 0; /* no tag */ From 10fef6bd6b3913c94d81276a271ac0c77c2c3525 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:40:23 -0500 Subject: [PATCH 19/23] aud: simplify header parsing also allows for removing some unused context fields --- libavformat/westwood_aud.c | 53 +++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 27dc3fae63..79f2198745 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -42,10 +42,8 @@ #define AUD_CHUNK_SIGNATURE 0x0000DEAF typedef struct WsAudDemuxContext { - int audio_samplerate; int audio_channels; - int audio_bits; - enum CodecID audio_type; + int audio_samplerate; int audio_stream_index; int64_t audio_frame_counter; } WsAudDemuxContext; @@ -97,37 +95,44 @@ static int wsaud_read_header(AVFormatContext *s, AVIOContext *pb = s->pb; AVStream *st; unsigned char header[AUD_HEADER_SIZE]; + int sample_rate, channels, codec; if (avio_read(pb, header, AUD_HEADER_SIZE) != AUD_HEADER_SIZE) return AVERROR(EIO); - wsaud->audio_samplerate = AV_RL16(&header[0]); - if (header[11] == 99) - wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS; - else if (header[11] == 1) - wsaud->audio_type = CODEC_ID_WESTWOOD_SND1; - else - return AVERROR_INVALIDDATA; - /* flag 0 indicates stereo */ - wsaud->audio_channels = (header[10] & 0x1) + 1; - /* flag 1 indicates 16 bit audio */ - wsaud->audio_bits = (((header[10] & 0x2) >> 1) + 1) * 8; + sample_rate = AV_RL16(&header[0]); + channels = (header[10] & 0x1) + 1; + codec = header[11]; /* initialize the audio decoder stream */ st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); - avpriv_set_pts_info(st, 64, 1, wsaud->audio_samplerate); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = wsaud->audio_type; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = wsaud->audio_channels; - st->codec->sample_rate = wsaud->audio_samplerate; - if (st->codec->codec_id == CODEC_ID_ADPCM_IMA_WS) { - st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 4; - } + switch (codec) { + case 1: + if (channels != 1) { + av_log_ask_for_sample(s, "Stereo WS-SND1 is not supported.\n"); + return AVERROR_PATCHWELCOME; + } + st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; + break; + case 99: + st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; + st->codec->bits_per_coded_sample = 4; + st->codec->bit_rate = channels * sample_rate * 4; + break; + default: + av_log_ask_for_sample(s, "Unknown codec: %d\n", codec); + return AVERROR_PATCHWELCOME; + } + avpriv_set_pts_info(st, 64, 1, sample_rate); + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->channels = channels; + st->codec->sample_rate = sample_rate; + + wsaud->audio_channels = channels; + wsaud->audio_samplerate = sample_rate; wsaud->audio_stream_index = st->index; wsaud->audio_frame_counter = 0; From be14a37066cc99e2b769ee5e044a34caecd24938 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:43:54 -0500 Subject: [PATCH 20/23] aud: fix time stamp calculation for ADPCM IMA WS also allows for removing some unused context fields --- libavformat/westwood_aud.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 79f2198745..2195accbc8 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -42,10 +42,7 @@ #define AUD_CHUNK_SIGNATURE 0x0000DEAF typedef struct WsAudDemuxContext { - int audio_channels; - int audio_samplerate; int audio_stream_index; - int64_t audio_frame_counter; } WsAudDemuxContext; static int wsaud_probe(AVProbeData *p) @@ -131,10 +128,7 @@ static int wsaud_read_header(AVFormatContext *s, st->codec->channels = channels; st->codec->sample_rate = sample_rate; - wsaud->audio_channels = channels; - wsaud->audio_samplerate = sample_rate; wsaud->audio_stream_index = st->index; - wsaud->audio_frame_counter = 0; return 0; } @@ -177,11 +171,9 @@ static int wsaud_read_packet(AVFormatContext *s, ret = av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR(EIO); - pkt->pts = wsaud->audio_frame_counter; - pkt->pts /= wsaud->audio_samplerate; /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ - wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels; + pkt->duration = (chunk_size * 2) / st->codec->channels; } pkt->stream_index = st->index; From b8dd555c63ca4ef1034006159b01f49e103c6252 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 24 Jan 2012 11:46:58 -0500 Subject: [PATCH 21/23] aud: remove unneeded field, audio_stream_index from context There is only one stream, so it will always be index 0. This also allows for removal of the private context. --- libavformat/westwood_aud.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index 2195accbc8..f083a86baf 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -41,10 +41,6 @@ #define AUD_CHUNK_PREAMBLE_SIZE 8 #define AUD_CHUNK_SIGNATURE 0x0000DEAF -typedef struct WsAudDemuxContext { - int audio_stream_index; -} WsAudDemuxContext; - static int wsaud_probe(AVProbeData *p) { int field; @@ -88,7 +84,6 @@ static int wsaud_probe(AVProbeData *p) static int wsaud_read_header(AVFormatContext *s, AVFormatParameters *ap) { - WsAudDemuxContext *wsaud = s->priv_data; AVIOContext *pb = s->pb; AVStream *st; unsigned char header[AUD_HEADER_SIZE]; @@ -128,20 +123,17 @@ static int wsaud_read_header(AVFormatContext *s, st->codec->channels = channels; st->codec->sample_rate = sample_rate; - wsaud->audio_stream_index = st->index; - return 0; } static int wsaud_read_packet(AVFormatContext *s, AVPacket *pkt) { - WsAudDemuxContext *wsaud = s->priv_data; AVIOContext *pb = s->pb; unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE]; unsigned int chunk_size; int ret = 0; - AVStream *st = s->streams[wsaud->audio_stream_index]; + AVStream *st = s->streams[0]; if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != AUD_CHUNK_PREAMBLE_SIZE) @@ -183,7 +175,6 @@ static int wsaud_read_packet(AVFormatContext *s, AVInputFormat ff_wsaud_demuxer = { .name = "wsaud", .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios audio format"), - .priv_data_size = sizeof(WsAudDemuxContext), .read_probe = wsaud_probe, .read_header = wsaud_read_header, .read_packet = wsaud_read_packet, From cdfe94c5ab1df40c6c724df5d4cafe2539c5571a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 23 Jan 2012 13:05:03 -0800 Subject: [PATCH 22/23] aacenc: Write correct length for long identification strings. When the length is the escape value (15), the new length is calculated by 15 + get_bits(8) - 1. Signed-off-by: Alex Converse --- libavcodec/aacenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 7607362142..b4045ab6eb 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -462,7 +462,7 @@ static void put_bitstream_info(AVCodecContext *avctx, AACEncContext *s, put_bits(&s->pb, 3, TYPE_FIL); put_bits(&s->pb, 4, FFMIN(namelen, 15)); if (namelen >= 15) - put_bits(&s->pb, 8, namelen - 16); + put_bits(&s->pb, 8, namelen - 14); put_bits(&s->pb, 4, 0); //extension type - filler padbits = 8 - (put_bits_count(&s->pb) & 7); avpriv_align_put_bits(&s->pb); From efe68076dab56293168ffb66d7b6c1977b740098 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Mon, 23 Jan 2012 13:08:32 -0800 Subject: [PATCH 23/23] aacenc: Fix identification padding when the bitstream is already aligned. --- libavcodec/aacenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index b4045ab6eb..d7a6d5a63c 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -464,7 +464,7 @@ static void put_bitstream_info(AVCodecContext *avctx, AACEncContext *s, if (namelen >= 15) put_bits(&s->pb, 8, namelen - 14); put_bits(&s->pb, 4, 0); //extension type - filler - padbits = 8 - (put_bits_count(&s->pb) & 7); + padbits = -put_bits_count(&s->pb) & 7; avpriv_align_put_bits(&s->pb); for (i = 0; i < namelen - 2; i++) put_bits(&s->pb, 8, name[i]);