From 45fcb86cf86a0dca43a196e927817efb188fd7da Mon Sep 17 00:00:00 2001 From: Mike Melanson Date: Mon, 7 Nov 2011 23:28:02 -0800 Subject: AIFF: add 'twos' FourCC for the mux/demuxer (big endian PCM audio) Signed-off-by: Anton Khirnov --- libavformat/aiff.h | 1 + 1 file changed, 1 insertion(+) (limited to 'libavformat') diff --git a/libavformat/aiff.h b/libavformat/aiff.h index cd2bd256d6..3190a22787 100644 --- a/libavformat/aiff.h +++ b/libavformat/aiff.h @@ -43,6 +43,7 @@ static const AVCodecTag ff_codec_aiff_tags[] = { { CODEC_ID_MACE6, MKTAG('M','A','C','6') }, { CODEC_ID_GSM, MKTAG('G','S','M',' ') }, { CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') }, + { CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') }, { CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, { CODEC_ID_ADPCM_IMA_QT, MKTAG('i','m','a','4') }, { CODEC_ID_QDM2, MKTAG('Q','D','M','2') }, -- cgit v1.2.3 From b01f5ba2070e022e6cf6c1fa8410367e90e33b60 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Thu, 10 Nov 2011 18:21:17 +0200 Subject: http: Print an error message for Authorization Required, too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error was hidden before, to avoid showing an error on the first request where no auth has been provided, when the server indicates which authentication method to use. Now the error is printed if an authentication method was used, but failed. Signed-off-by: Martin Storsjö --- libavformat/http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'libavformat') diff --git a/libavformat/http.c b/libavformat/http.c index 83ffc0b60e..093bb822dc 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -236,7 +236,8 @@ static int process_line(URLContext *h, char *line, int line_count, /* error codes are 4xx and 5xx, but regard 401 as a success, so we * don't abort until all headers have been parsed. */ - if (s->http_code >= 400 && s->http_code < 600 && s->http_code != 401) { + if (s->http_code >= 400 && s->http_code < 600 && (s->http_code != 401 + || s->auth_state.auth_type != HTTP_AUTH_NONE)) { end += strspn(end, SPACE_CHARS); av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", s->http_code, end); -- cgit v1.2.3 From b911518d1c17223aa7fb83ace08b2bd41c203da0 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Fri, 11 Nov 2011 11:21:42 +0200 Subject: http: Handle proxy authentication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested with both Basic and Digest authentication, and tested with both proxy authentication and authentication for the requested resource at the same time. Signed-off-by: Martin Storsjö --- libavformat/http.c | 75 ++++++++++++++++++++++++++++++++++---------------- libavformat/httpauth.c | 2 +- 2 files changed, 53 insertions(+), 24 deletions(-) (limited to 'libavformat') diff --git a/libavformat/http.c b/libavformat/http.c index 093bb822dc..a8a76882dd 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -47,6 +47,7 @@ typedef struct { int64_t off, filesize; char location[MAX_URL_SIZE]; HTTPAuthState auth_state; + HTTPAuthState proxy_auth_state; char *headers; int willclose; /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */ int chunked_post; @@ -71,25 +72,29 @@ static const AVClass flavor ## _context_class = {\ HTTP_CLASS(http); HTTP_CLASS(https); -static int http_connect(URLContext *h, const char *path, const char *hoststr, - const char *auth, int *new_location); +static int http_connect(URLContext *h, const char *path, const char *local_path, + const char *hoststr, const char *auth, + const char *proxyauth, int *new_location); void ff_http_init_auth_state(URLContext *dest, const URLContext *src) { memcpy(&((HTTPContext*)dest->priv_data)->auth_state, &((HTTPContext*)src->priv_data)->auth_state, sizeof(HTTPAuthState)); + memcpy(&((HTTPContext*)dest->priv_data)->proxy_auth_state, + &((HTTPContext*)src->priv_data)->proxy_auth_state, + sizeof(HTTPAuthState)); } /* return non zero if error */ static int http_open_cnx(URLContext *h) { - const char *path, *proxy_path, *lower_proto = "tcp"; + const char *path, *proxy_path, *lower_proto = "tcp", *local_path; char hostname[1024], hoststr[1024], proto[10]; - char auth[1024]; + char auth[1024], proxyauth[1024]; char path1[1024]; - char buf[1024]; + char buf[1024], urlbuf[1024]; int port, use_proxy, err, location_changed = 0, redirects = 0; - HTTPAuthType cur_auth_type; + HTTPAuthType cur_auth_type, cur_proxy_auth_type; HTTPContext *s = h->priv_data; URLContext *hd = NULL; @@ -105,15 +110,19 @@ static int http_open_cnx(URLContext *h) path1, sizeof(path1), s->location); ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); + if (path1[0] == '\0') + path = "/"; + else + path = path1; + local_path = path; if (use_proxy) { - av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, - NULL, 0, proxy_path); - path = s->location; - } else { - if (path1[0] == '\0') - path = "/"; - else - path = path1; + /* Reassemble the request URL without auth string - we don't + * want to leak the auth to the proxy. */ + ff_url_join(urlbuf, sizeof(urlbuf), proto, NULL, hostname, port, "%s", + path1); + path = urlbuf; + av_url_split(NULL, 0, proxyauth, sizeof(proxyauth), + hostname, sizeof(hostname), &port, NULL, 0, proxy_path); } if (!strcmp(proto, "https")) { lower_proto = "tls"; @@ -130,7 +139,8 @@ static int http_open_cnx(URLContext *h) s->hd = hd; cur_auth_type = s->auth_state.auth_type; - if (http_connect(h, path, hoststr, auth, &location_changed) < 0) + cur_proxy_auth_type = s->auth_state.auth_type; + if (http_connect(h, path, local_path, hoststr, auth, proxyauth, &location_changed) < 0) goto fail; if (s->http_code == 401) { if (cur_auth_type == HTTP_AUTH_NONE && s->auth_state.auth_type != HTTP_AUTH_NONE) { @@ -139,6 +149,14 @@ static int http_open_cnx(URLContext *h) } else goto fail; } + if (s->http_code == 407) { + if (cur_proxy_auth_type == HTTP_AUTH_NONE && + s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) { + ffurl_close(hd); + goto redo; + } else + goto fail; + } if ((s->http_code == 301 || s->http_code == 302 || s->http_code == 303 || s->http_code == 307) && location_changed == 1) { /* url moved, get next */ @@ -237,7 +255,8 @@ static int process_line(URLContext *h, char *line, int line_count, /* error codes are 4xx and 5xx, but regard 401 as a success, so we * don't abort until all headers have been parsed. */ if (s->http_code >= 400 && s->http_code < 600 && (s->http_code != 401 - || s->auth_state.auth_type != HTTP_AUTH_NONE)) { + || s->auth_state.auth_type != HTTP_AUTH_NONE) && + (s->http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) { end += strspn(end, SPACE_CHARS); av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", s->http_code, end); @@ -278,6 +297,8 @@ static int process_line(URLContext *h, char *line, int line_count, ff_http_auth_handle_header(&s->auth_state, tag, p); } else if (!av_strcasecmp (tag, "Authentication-Info")) { ff_http_auth_handle_header(&s->auth_state, tag, p); + } else if (!av_strcasecmp (tag, "Proxy-Authenticate")) { + ff_http_auth_handle_header(&s->proxy_auth_state, tag, p); } else if (!av_strcasecmp (tag, "Connection")) { if (!strcmp(p, "close")) s->willclose = 1; @@ -294,22 +315,27 @@ static inline int has_header(const char *str, const char *header) return av_stristart(str, header + 2, NULL) || av_stristr(str, header); } -static int http_connect(URLContext *h, const char *path, const char *hoststr, - const char *auth, int *new_location) +static int http_connect(URLContext *h, const char *path, const char *local_path, + const char *hoststr, const char *auth, + const char *proxyauth, int *new_location) { HTTPContext *s = h->priv_data; int post, err; char line[1024]; char headers[1024] = ""; - char *authstr = NULL; + char *authstr = NULL, *proxyauthstr = NULL; int64_t off = s->off; int len = 0; + const char *method; /* send http header */ post = h->flags & AVIO_FLAG_WRITE; - authstr = ff_http_auth_create_response(&s->auth_state, auth, path, - post ? "POST" : "GET"); + method = post ? "POST" : "GET"; + authstr = ff_http_auth_create_response(&s->auth_state, auth, local_path, + method); + proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth, + local_path, method); /* set default headers if needed */ if (!has_header(s->headers, "\r\nUser-Agent: ")) @@ -337,14 +363,17 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, "%s" "%s" "%s" + "%s%s" "\r\n", - post ? "POST" : "GET", + method, path, post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "", headers, - authstr ? authstr : ""); + authstr ? authstr : "", + proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : ""); av_freep(&authstr); + av_freep(&proxyauthstr); if (ffurl_write(s->hd, s->buffer, strlen(s->buffer)) < 0) return AVERROR(EIO); diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index 1dda1ac8f0..c8b8ace3c2 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -87,7 +87,7 @@ static void choose_qop(char *qop, int size) void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, const char *value) { - if (!strcmp(key, "WWW-Authenticate")) { + if (!strcmp(key, "WWW-Authenticate") || !strcmp(key, "Proxy-Authenticate")) { const char *p; if (av_stristart(value, "Basic ", &p) && state->auth_type <= HTTP_AUTH_BASIC) { -- cgit v1.2.3 From b8a1b880ee155f4f27389f7f76a58a1d87eb7008 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Wed, 9 Nov 2011 16:28:35 -0700 Subject: rtpdec: Simplify finalize_packet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtpdec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'libavformat') diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 1e6bd6eee7..a5ec1caf7a 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -421,7 +421,10 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam { if (pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE) return; /* Timestamp already set by depacketizer */ - if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE && timestamp != RTP_NOTS_VALUE) { + if (timestamp == RTP_NOTS_VALUE) + return; + + if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { int64_t addend; int delta_timestamp; @@ -433,8 +436,7 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam delta_timestamp; return; } - if (timestamp == RTP_NOTS_VALUE) - return; + if (!s->base_timestamp) s->base_timestamp = timestamp; pkt->pts = s->range_start_offset + timestamp - s->base_timestamp; -- cgit v1.2.3 From ca482ce4204fe198b2df1b41f3d15e883f3f1f0d Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sat, 29 Oct 2011 19:24:55 -0400 Subject: vqf: do not set bits_per_coded_sample for TwinVQ. It is a lossy codec with varying quantization, so bits_per_coded_sample is not applicable. --- libavformat/vqf.c | 1 - 1 file changed, 1 deletion(-) (limited to 'libavformat') diff --git a/libavformat/vqf.c b/libavformat/vqf.c index 71dc1ae73d..4650a0b500 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -106,7 +106,6 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) avio_skip(s->pb, len-12); st->codec->bit_rate = read_bitrate*1000; - st->codec->bits_per_coded_sample = 16; break; case MKTAG('N','A','M','E'): add_metadata(s, "title" , len, header_size); -- cgit v1.2.3 From 7b966566da24598a636a433a75a7842e272b18f6 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 30 Oct 2011 00:46:16 -0400 Subject: vqf/twinvq: pass vqf COMM chunk info in extradata This is needed because the twinvq decoder cannot rely on bit_rate to be set. The API documentation says that bit_rate is set by libavcodec, not by the user. --- libavcodec/twinvq.c | 18 ++++++++++++++++-- libavformat/vqf.c | 14 +++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'libavformat') diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c index 174cee7424..73eb7c1499 100644 --- a/libavcodec/twinvq.c +++ b/libavcodec/twinvq.c @@ -1104,17 +1104,31 @@ static av_cold int twin_decode_init(AVCodecContext *avctx) { int ret; TwinContext *tctx = avctx->priv_data; - int isampf = avctx->sample_rate/1000; - int ibps = avctx->bit_rate/(1000 * avctx->channels); + int isampf, ibps; tctx->avctx = avctx; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; + if (!avctx->extradata || avctx->extradata_size < 12) { + av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n"); + return AVERROR_INVALIDDATA; + } + avctx->channels = AV_RB32(avctx->extradata ) + 1; + avctx->bit_rate = AV_RB32(avctx->extradata + 4) * 1000; + isampf = AV_RB32(avctx->extradata + 8); + switch (isampf) { + case 44: avctx->sample_rate = 44100; break; + case 22: avctx->sample_rate = 22050; break; + case 11: avctx->sample_rate = 11025; break; + default: avctx->sample_rate = isampf * 1000; break; + } + if (avctx->channels > CHANNELS_MAX) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n", avctx->channels); return -1; } + ibps = avctx->bit_rate / (1000 * avctx->channels); switch ((isampf << 8) + ibps) { case (8 <<8) + 8: tctx->mtab = &mode_08_08; break; diff --git a/libavformat/vqf.c b/libavformat/vqf.c index 4650a0b500..f2c1d8f146 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -70,6 +70,7 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) int header_size; int read_bitrate = 0; int size; + uint8_t comm_chunk[12]; if (!st) return AVERROR(ENOMEM); @@ -100,9 +101,10 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) switch(chunk_tag){ case MKTAG('C','O','M','M'): - st->codec->channels = avio_rb32(s->pb) + 1; - read_bitrate = avio_rb32(s->pb); - rate_flag = avio_rb32(s->pb); + avio_read(s->pb, comm_chunk, 12); + st->codec->channels = AV_RB32(comm_chunk ) + 1; + read_bitrate = AV_RB32(comm_chunk + 4); + rate_flag = AV_RB32(comm_chunk + 8); avio_skip(s->pb, len-12); st->codec->bit_rate = read_bitrate*1000; @@ -192,6 +194,12 @@ static int vqf_read_header(AVFormatContext *s, AVFormatParameters *ap) c->frame_bit_len = st->codec->bit_rate*size/st->codec->sample_rate; av_set_pts_info(st, 64, 1, st->codec->sample_rate); + /* put first 12 bytes of COMM chunk in extradata */ + if (!(st->codec->extradata = av_malloc(12 + FF_INPUT_BUFFER_PADDING_SIZE))) + return AVERROR(ENOMEM); + st->codec->extradata_size = 12; + memcpy(st->codec->extradata, comm_chunk, 12); + return 0; } -- cgit v1.2.3 From c433a3f9a5ead7bd107384e20ea21de9f4c3f911 Mon Sep 17 00:00:00 2001 From: Derek Buitenhuis Date: Fri, 11 Nov 2011 14:46:19 -0500 Subject: VBLE Decoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a decoder for the VBLE Lossless Codec, which still has a cult following. Used to be popular several years ago on doom9. Signed-off-by: Derek Buitenhuis Signed-off-by: Martin Storsjö --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/vble.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 2 +- libavformat/riff.c | 1 + 8 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 libavcodec/vble.c (limited to 'libavformat') diff --git a/Changelog b/Changelog index 5387a6522f..a322c9d0d5 100644 --- a/Changelog +++ b/Changelog @@ -100,6 +100,7 @@ easier to use. The changes are: - Properly working defaults in libx264 wrapper, support for native presets. - Encrypted OMA files support - Discworld II BMV decoding support +- VBLE Decoder version 0.7: diff --git a/doc/general.texi b/doc/general.texi index 3187f2cc78..d2747c052c 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -520,6 +520,7 @@ following image formats are supported: @tab Codec used in DOS CD-ROM FlashBack game. @item Ut Video @tab @tab X @item V210 Quicktime Uncompressed 4:2:2 10-bit @tab X @tab X +@item VBLE Lossless Codec @tab @tab X @item VMware Screen Codec / VMware Video @tab @tab X @tab Codec used in videos captured by VMware. @item Westwood Studios VQA (Vector Quantized Animation) video @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 5fabd8b7fc..76d5ce0707 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -383,6 +383,7 @@ OBJS-$(CONFIG_V210_DECODER) += v210dec.o OBJS-$(CONFIG_V210_ENCODER) += v210enc.o OBJS-$(CONFIG_V210X_DECODER) += v210x.o OBJS-$(CONFIG_VB_DECODER) += vb.o +OBJS-$(CONFIG_VBLE_DECODER) += vble.o OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \ msmpeg4.o msmpeg4data.o \ intrax8.o intrax8dsp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index e9be06398d..a4a2147f94 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -203,6 +203,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (V210, v210); REGISTER_DECODER (V210X, v210x); REGISTER_DECODER (VB, vb); + REGISTER_DECODER (VBLE, vble); REGISTER_DECODER (VC1, vc1); REGISTER_DECODER (VC1_VDPAU, vc1_vdpau); REGISTER_DECODER (VC1IMAGE, vc1image); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 76562834ed..7d506a1f72 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -220,6 +220,7 @@ enum CodecID { #endif CODEC_ID_UTVIDEO, CODEC_ID_BMV_VIDEO, + CODEC_ID_VBLE, /* various PCM "codecs" */ CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/vble.c b/libavcodec/vble.c new file mode 100644 index 0000000000..436402ded4 --- /dev/null +++ b/libavcodec/vble.c @@ -0,0 +1,248 @@ +/* + * VBLE Decoder + * Copyright (c) 2011 Derek Buitenhuis + * + * 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 + */ + +/** + * @file + * VBLE Decoder + */ + +#define ALT_BITSTREAM_READER_LE + +#include "avcodec.h" +#include "get_bits.h" + +typedef struct { + AVCodecContext *avctx; + + int size; + int flags; + uint8_t *len; + uint8_t *val; +} VBLEContext; + +static uint8_t vble_read_reverse_unary(GetBitContext *gb) +{ + /* At most we need to read 9 bits total to get indices up to 8 */ + uint8_t val = show_bits(gb, 8); + + if (val) { + val = 7 - av_log2_16bit(av_reverse[val]); + skip_bits(gb, val + 1); + return val; + } else { + skip_bits(gb, 8); + if (get_bits1(gb)) + return 8; + } + + /* Return something larger than 8 on error */ + return UINT8_MAX; +} + +static int vble_unpack(VBLEContext *ctx, GetBitContext *gb) +{ + int i; + + /* Read all the lengths in first */ + for (i = 0; i < ctx->size; i++) { + ctx->len[i] = vble_read_reverse_unary(gb); + + if (ctx->len[i] == UINT8_MAX) + return -1; + } + + /* For any values that have length 0 */ + memset(ctx->val, 0, ctx->size); + + for (i = 0; i < ctx->size; i++) { + /* Check we have enough bits left */ + if (get_bits_left(gb) < ctx->len[i]) + return -1; + + /* get_bits can't take a length of 0 */ + if (ctx->len[i]) + ctx->val[i] = (1 << ctx->len[i]) + get_bits(gb, ctx->len[i]) - 1; + } + + return 0; +} + +static void vble_restore_plane(VBLEContext *ctx, int plane, int offset, + int width, int height) +{ + AVFrame *pic = ctx->avctx->coded_frame; + uint8_t *dst = pic->data[plane]; + uint8_t *val = ctx->val + offset; + uint8_t *len = ctx->len + offset; + uint8_t a, b, c; + int stride = pic->linesize[plane]; + int i, j; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + dst[j] = (val[j] >> 1) ^ -(val[j] & 1); + + /* Top line and left column are not predicted */ + if (!j) + continue; + + if (!i) { + dst[j] += dst[j - 1]; + continue; + } + + a = dst[j - 1]; + b = dst[j - stride]; + c = a + b - dst[j - 1 - stride]; + dst[j] += mid_pred(a, b, c); + } + dst += stride; + val += width; + len += width; + } +} + +static int vble_decode_frame(AVCodecContext *avctx, void *data, int *data_size, + AVPacket *avpkt) +{ + VBLEContext *ctx = avctx->priv_data; + AVFrame *pic = avctx->coded_frame; + GetBitContext gb; + const uint8_t *src = avpkt->data; + int version; + int offset = 0; + int width_uv = avctx->width / 2, height_uv = avctx->height / 2; + + pic->reference = 0; + + /* Clear buffer if need be */ + if (pic->data[0]) + avctx->release_buffer(avctx, pic); + + /* Allocate buffer */ + if (avctx->get_buffer(avctx, pic) < 0) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n"); + return AVERROR(ENOMEM); + } + + /* Set flags */ + pic->key_frame = 1; + pic->pict_type = FF_I_TYPE; + + /* Version should always be 1 */ + version = AV_RL32(src); + + if (version != 1) { + av_log(avctx, AV_LOG_ERROR, "Unsupported VBLE Version: %d\n", version); + return AVERROR_INVALIDDATA; + } + + init_get_bits(&gb, src + 4, (avpkt->size - 4) * 8); + + /* Unpack */ + if (vble_unpack(ctx, &gb) < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid Code\n"); + return AVERROR_INVALIDDATA; + } + + /* Restore planes. Should be almost identical to Huffyuv's. */ + vble_restore_plane(ctx, 0, offset, avctx->width, avctx->height); + + /* Chroma */ + if (!(ctx->flags & CODEC_FLAG_GRAY)) { + offset += avctx->width * avctx->height; + vble_restore_plane(ctx, 1, offset, width_uv, height_uv); + + offset += width_uv * height_uv; + vble_restore_plane(ctx, 2, offset, width_uv, height_uv); + } + + *data_size = sizeof(AVFrame); + *(AVFrame *)data = *pic; + + return avpkt->size; +} + +static av_cold int vble_decode_close(AVCodecContext *avctx) +{ + VBLEContext *ctx = avctx->priv_data; + AVFrame *pic = avctx->coded_frame; + + if (pic->data[0]) + avctx->release_buffer(avctx, pic); + + av_freep(&avctx->coded_frame); + av_freep(&ctx->len); + av_freep(&ctx->val); + + return 0; +} + +static av_always_inline int vble_error_close(AVCodecContext *avctx, + const char *message) +{ + av_log(avctx, AV_LOG_ERROR, message); + vble_decode_close(avctx); + return AVERROR(ENOMEM); +} + +static av_cold int vble_decode_init(AVCodecContext *avctx) +{ + VBLEContext *ctx = avctx->priv_data; + + /* Stash for later use */ + ctx->avctx = avctx; + ctx->flags = avctx->flags; + + avctx->pix_fmt = PIX_FMT_YUV420P; + avctx->bits_per_raw_sample = 8; + avctx->coded_frame = avcodec_alloc_frame(); + + if (!avctx->coded_frame) + return vble_error_close(avctx, "Could not allocate frame.\n"); + + ctx->size = avpicture_get_size(avctx->pix_fmt, + avctx->width, avctx->height); + + ctx->len = av_malloc(ctx->size * sizeof(*ctx->len)); + + if (!ctx->len) + return vble_error_close(avctx, "Could not allocate lengths buffer.\n"); + + ctx->val = av_malloc(ctx->size * sizeof(*ctx->val)); + + if (!ctx->val) + return vble_error_close(avctx, "Could not allocate values buffer.\n"); + + return 0; +} + +AVCodec ff_vble_decoder = { + .name = "vble", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_VBLE, + .priv_data_size = sizeof(VBLEContext), + .init = vble_decode_init, + .close = vble_decode_close, + .decode = vble_decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index c11f09c9d4..756ad1d223 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 18 +#define LIBAVCODEC_VERSION_MINOR 19 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/riff.c b/libavformat/riff.c index 8eed7ce28e..29c3803173 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -279,6 +279,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'R', 'G') }, { CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '0') }, { CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '2') }, + { CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { CODEC_ID_NONE, 0 } }; -- cgit v1.2.3