Unified · Split
| @@ -99,6 +99,7 @@ easier to use. The changes are: · 98 unmodified lines | |||
| 99 | AVCodecContext deprecated. Codec private options should be used instead. | 99 | AVCodecContext deprecated. Codec private options should be used instead. |
| 100 | - Properly working defaults in libx264 wrapper, support for native presets. | 100 | - Properly working defaults in libx264 wrapper, support for native presets. |
| 101 | - Encrypted OMA files support | 101 | - Encrypted OMA files support |
| 102 | - Discworld II BMV decoding support | ||
| 102 | 103 | ||
| 103 | 104 | ||
| 104 | version 0.7: | 105 | version 0.7: |
| @@ -67,6 +67,7 @@ library: · 66 unmodified lines | |||
| 67 | @item Brute Force & Ignorance @tab @tab X | 67 | @item Brute Force & Ignorance @tab @tab X |
| 68 | @tab Used in the game Flash Traffic: City of Angels. | 68 | @tab Used in the game Flash Traffic: City of Angels. |
| 69 | @item BWF @tab X @tab X | 69 | @item BWF @tab X @tab X |
| 70 | @item Discworld II BMV @tab @tab X | ||
| 70 | @item Interplay C93 @tab @tab X | 71 | @item Interplay C93 @tab @tab X |
| 71 | @tab Used in the game Cyberia from Interplay. | 72 | @tab Used in the game Cyberia from Interplay. |
| 72 | @item Delphine Software International CIN @tab @tab X | 73 | @item Delphine Software International CIN @tab @tab X |
| @@ -376,6 +377,7 @@ following image formats are supported: · 303 unmodified lines | |||
| 376 | @tab AVS1-P2, JiZhun profile, encoding through external library libxavs | 377 | @tab AVS1-P2, JiZhun profile, encoding through external library libxavs |
| 377 | @item Delphine Software International CIN video @tab @tab X | 378 | @item Delphine Software International CIN video @tab @tab X |
| 378 | @tab Codec used in Delphine Software International games. | 379 | @tab Codec used in Delphine Software International games. |
| 380 | @item Discworld II BMV Video @tab @tab X | ||
| 379 | @item Cinepak @tab @tab X | 381 | @item Cinepak @tab @tab X |
| 380 | @item Cirrus Logic AccuPak @tab @tab X | 382 | @item Cirrus Logic AccuPak @tab @tab X |
| 381 | @tab fourcc: CLJR | 383 | @tab fourcc: CLJR |
| @@ -608,6 +610,7 @@ following image formats are supported: · 226 unmodified lines | |||
| 608 | @tab Used in Bink and Smacker files in many games. | 610 | @tab Used in Bink and Smacker files in many games. |
| 609 | @item Delphine Software International CIN audio @tab @tab X | 611 | @item Delphine Software International CIN audio @tab @tab X |
| 610 | @tab Codec used in Delphine Software International games. | 612 | @tab Codec used in Delphine Software International games. |
| 613 | @item Discworld II BMV Audio @tab @tab X | ||
| 611 | @item COOK @tab @tab X | 614 | @item COOK @tab @tab X |
| 612 | @tab All versions except 5.1 are supported. | 615 | @tab All versions except 5.1 are supported. |
| 613 | @item DCA (DTS Coherent Acoustics) @tab @tab X | 616 | @item DCA (DTS Coherent Acoustics) @tab @tab X |
| @@ -94,6 +94,8 @@ OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o wma.o · 93 unmodified lines | |||
| 94 | OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o | 94 | OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o wma.o |
| 95 | OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o | 95 | OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o |
| 96 | OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o | 96 | OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o |
| 97 | OBJS-$(CONFIG_BMV_VIDEO_DECODER) += bmv.o | ||
| 98 | OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmv.o | ||
| 97 | OBJS-$(CONFIG_C93_DECODER) += c93.o | 99 | OBJS-$(CONFIG_C93_DECODER) += c93.o |
| 98 | OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ | 100 | OBJS-$(CONFIG_CAVS_DECODER) += cavs.o cavsdec.o cavsdsp.o \ |
| 99 | mpeg12data.o mpegvideo.o | 101 | mpeg12data.o mpegvideo.o |
| @@ -81,6 +81,7 @@ void avcodec_register_all(void) · 80 unmodified lines | |||
| 81 | REGISTER_DECODER (BFI, bfi); | 81 | REGISTER_DECODER (BFI, bfi); |
| 82 | REGISTER_DECODER (BINK, bink); | 82 | REGISTER_DECODER (BINK, bink); |
| 83 | REGISTER_ENCDEC (BMP, bmp); | 83 | REGISTER_ENCDEC (BMP, bmp); |
| 84 | REGISTER_DECODER (BMV_VIDEO, bmv_video); | ||
| 84 | REGISTER_DECODER (C93, c93); | 85 | REGISTER_DECODER (C93, c93); |
| 85 | REGISTER_DECODER (CAVS, cavs); | 86 | REGISTER_DECODER (CAVS, cavs); |
| 86 | REGISTER_DECODER (CDGRAPHICS, cdgraphics); | 87 | REGISTER_DECODER (CDGRAPHICS, cdgraphics); |
| @@ -242,6 +243,7 @@ void avcodec_register_all(void) · 155 unmodified lines | |||
| 242 | REGISTER_DECODER (ATRAC3, atrac3); | 243 | REGISTER_DECODER (ATRAC3, atrac3); |
| 243 | REGISTER_DECODER (BINKAUDIO_DCT, binkaudio_dct); | 244 | REGISTER_DECODER (BINKAUDIO_DCT, binkaudio_dct); |
| 244 | REGISTER_DECODER (BINKAUDIO_RDFT, binkaudio_rdft); | 245 | REGISTER_DECODER (BINKAUDIO_RDFT, binkaudio_rdft); |
| 246 | REGISTER_DECODER (BMV_AUDIO, bmv_audio); | ||
| 245 | REGISTER_DECODER (COOK, cook); | 247 | REGISTER_DECODER (COOK, cook); |
| 246 | REGISTER_DECODER (DCA, dca); | 248 | REGISTER_DECODER (DCA, dca); |
| 247 | REGISTER_DECODER (DSICINAUDIO, dsicinaudio); | 249 | REGISTER_DECODER (DSICINAUDIO, dsicinaudio); |
| @@ -219,6 +219,7 @@ enum CodecID { · 218 unmodified lines | |||
| 219 | CODEC_ID_G729, | 219 | CODEC_ID_G729, |
| 220 | #endif | 220 | #endif |
| 221 | CODEC_ID_UTVIDEO, | 221 | CODEC_ID_UTVIDEO, |
| 222 | CODEC_ID_BMV_VIDEO, | ||
| 222 | 223 | ||
| 223 | /* various PCM "codecs" */ | 224 | /* various PCM "codecs" */ |
| 224 | CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs | 225 | CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs |
| @@ -359,6 +360,7 @@ enum CodecID { · 134 unmodified lines | |||
| 359 | CODEC_ID_8SVX_EXP, | 360 | CODEC_ID_8SVX_EXP, |
| 360 | CODEC_ID_8SVX_FIB, | 361 | CODEC_ID_8SVX_FIB, |
| 361 | #endif | 362 | #endif |
| 363 | CODEC_ID_BMV_AUDIO, | ||
| 362 | 364 | ||
| 363 | /* subtitle codecs */ | 365 | /* subtitle codecs */ |
| 364 | CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. | 366 | CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. |
| @@ -0,0 +1,360 @@ | |||
| 1 | /* | ||
| 2 | * Discworld II BMV video and audio decoder | ||
| 3 | * Copyright (c) 2011 Konstantin Shishkov | ||
| 4 | * | ||
| 5 | * This file is part of Libav. | ||
| 6 | * | ||
| 7 | * Libav is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * Libav is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with Libav; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "avcodec.h" | ||
| 23 | #include "bytestream.h" | ||
| 24 | |||
| 25 | enum BMVFlags{ | ||
| 26 | BMV_NOP = 0, | ||
| 27 | BMV_END, | ||
| 28 | BMV_DELTA, | ||
| 29 | BMV_INTRA, | ||
| 30 | |||
| 31 | BMV_SCROLL = 0x04, | ||
| 32 | BMV_PALETTE = 0x08, | ||
| 33 | BMV_COMMAND = 0x10, | ||
| 34 | BMV_AUDIO = 0x20, | ||
| 35 | BMV_EXT = 0x40, | ||
| 36 | BMV_PRINT = 0x80 | ||
| 37 | }; | ||
| 38 | |||
| 39 | #define SCREEN_WIDE 640 | ||
| 40 | #define SCREEN_HIGH 429 | ||
| 41 | |||
| 42 | typedef struct BMVDecContext { | ||
| 43 | AVCodecContext *avctx; | ||
| 44 | AVFrame pic; | ||
| 45 | |||
| 46 | uint8_t *frame, frame_base[SCREEN_WIDE * (SCREEN_HIGH + 1)]; | ||
| 47 | uint32_t pal[256]; | ||
| 48 | const uint8_t *stream; | ||
| 49 | } BMVDecContext; | ||
| 50 | |||
| 51 | #define NEXT_BYTE(v) v = forward ? v + 1 : v - 1; | ||
| 52 | |||
| 53 | static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, int frame_off) | ||
| 54 | { | ||
| 55 | int val, saved_val = 0; | ||
| 56 | int tmplen = src_len; | ||
| 57 | const uint8_t *src, *source_end = source + src_len; | ||
| 58 | uint8_t *frame_end = frame + SCREEN_WIDE * SCREEN_HIGH; | ||
| 59 | uint8_t *dst, *dst_end; | ||
| 60 | int len, mask; | ||
| 61 | int forward = (frame_off <= -SCREEN_WIDE) || (frame_off >= 0); | ||
| 62 | int read_two_nibbles, flag; | ||
| 63 | int advance_mode; | ||
| 64 | int mode = 0; | ||
| 65 | int i; | ||
| 66 | |||
| 67 | if (src_len <= 0) | ||
| 68 | return -1; | ||
| 69 | |||
| 70 | if (forward) { | ||
| 71 | src = source; | ||
| 72 | dst = frame; | ||
| 73 | dst_end = frame_end; | ||
| 74 | } else { | ||
| 75 | src = source + src_len - 1; | ||
| 76 | dst = frame_end - 1; | ||
| 77 | dst_end = frame - 1; | ||
| 78 | } | ||
| 79 | for (;;) { | ||
| 80 | int shift = 0; | ||
| 81 | flag = 0; | ||
| 82 | |||
| 83 | /* The mode/len decoding is a bit strange: | ||
| 84 | * values are coded as variable-length codes with nibble units, | ||
| 85 | * code end is signalled by two top bits in the nibble being nonzero. | ||
| 86 | * And since data is bytepacked and we read two nibbles at a time, | ||
| 87 | * we may get a nibble belonging to the next code. | ||
| 88 | * Hence this convoluted loop. | ||
| 89 | */ | ||
| 90 | if (!mode || (tmplen == 4)) { | ||
| 91 | if (src < source || src >= source_end) | ||
| 92 | return -1; | ||
| 93 | val = *src; | ||
| 94 | read_two_nibbles = 1; | ||
| 95 | } else { | ||
| 96 | val = saved_val; | ||
| 97 | read_two_nibbles = 0; | ||
| 98 | } | ||
| 99 | if (!(val & 0xC)) { | ||
| 100 | for (;;) { | ||
| 101 | if (!read_two_nibbles) { | ||
| 102 | if (src < source || src >= source_end) | ||
| 103 | return -1; | ||
| 104 | shift += 2; | ||
| 105 | val |= *src << shift; | ||
| 106 | if (*src & 0xC) | ||
| 107 | break; | ||
| 108 | } | ||
| 109 | // two upper bits of the nibble is zero, | ||
| 110 | // so shift top nibble value down into their place | ||
| 111 | read_two_nibbles = 0; | ||
| 112 | shift += 2; | ||
| 113 | mask = (1 << shift) - 1; | ||
| 114 | val = ((val >> 2) & ~mask) | (val & mask); | ||
| 115 | NEXT_BYTE(src); | ||
| 116 | if ((val & (0xC << shift))) { | ||
| 117 | flag = 1; | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | } else if (mode) { | ||
| 122 | flag = tmplen != 4; | ||
| 123 | } | ||
| 124 | if (flag) { | ||
| 125 | tmplen = 4; | ||
| 126 | } else { | ||
| 127 | saved_val = val >> (4 + shift); | ||
| 128 | tmplen = 0; | ||
| 129 | val &= (1 << (shift + 4)) - 1; | ||
| 130 | NEXT_BYTE(src); | ||
| 131 | } | ||
| 132 | advance_mode = val & 1; | ||
| 133 | len = (val >> 1) - 1; | ||
| 134 | mode += 1 + advance_mode; | ||
| 135 | if (mode >= 4) | ||
| 136 | mode -= 3; | ||
| 137 | if (FFABS(dst_end - dst) < len) | ||
| 138 | return -1; | ||
| 139 | switch (mode) { | ||
| 140 | case 1: | ||
| 141 | if (forward) { | ||
| 142 | if (dst - frame + SCREEN_WIDE < frame_off || | ||
| 143 | frame_end - dst < frame_off + len) | ||
| 144 | return -1; | ||
| 145 | for (i = 0; i < len; i++) | ||
| 146 | dst[i] = dst[frame_off + i]; | ||
| 147 | dst += len; | ||
| 148 | } else { | ||
| 149 | dst -= len; | ||
| 150 | if (dst - frame + SCREEN_WIDE < frame_off || | ||
| 151 | frame_end - dst < frame_off + len) | ||
| 152 | return -1; | ||
| 153 | for (i = len - 1; i >= 0; i--) | ||
| 154 | dst[i] = dst[frame_off + i]; | ||
| 155 | } | ||
| 156 | break; | ||
| 157 | case 2: | ||
| 158 | if (forward) { | ||
| 159 | if (source + src_len - src < len) | ||
| 160 | return -1; | ||
| 161 | memcpy(dst, src, len); | ||
| 162 | dst += len; | ||
| 163 | src += len; | ||
| 164 | } else { | ||
| 165 | if (src - source < len) | ||
| 166 | return -1; | ||
| 167 | dst -= len; | ||
| 168 | src -= len; | ||
| 169 | memcpy(dst, src, len); | ||
| 170 | } | ||
| 171 | break; | ||
| 172 | case 3: | ||
| 173 | val = forward ? dst[-1] : dst[1]; | ||
| 174 | if (forward) { | ||
| 175 | memset(dst, val, len); | ||
| 176 | dst += len; | ||
| 177 | } else { | ||
| 178 | dst -= len; | ||
| 179 | memset(dst, val, len); | ||
| 180 | } | ||
| 181 | break; | ||
| 182 | default: | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | if (dst == dst_end) | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt) | ||
| 192 | { | ||
| 193 | BMVDecContext * const c = avctx->priv_data; | ||
| 194 | int type, scr_off; | ||
| 195 | int i; | ||
| 196 | uint8_t *srcptr, *outptr; | ||
| 197 | |||
| 198 | c->stream = pkt->data; | ||
| 199 | type = bytestream_get_byte(&c->stream); | ||
| 200 | if (type & BMV_AUDIO) { | ||
| 201 | int blobs = bytestream_get_byte(&c->stream); | ||
| 202 | if (pkt->size < blobs * 65 + 2) { | ||
| 203 | av_log(avctx, AV_LOG_ERROR, "Audio data doesn't fit in frame\n"); | ||
| 204 | return AVERROR_INVALIDDATA; | ||
| 205 | } | ||
| 206 | c->stream += blobs * 65; | ||
| 207 | } | ||
| 208 | if (type & BMV_COMMAND) { | ||
| 209 | int command_size = (type & BMV_PRINT) ? 8 : 10; | ||
| 210 | if (c->stream - pkt->data + command_size > pkt->size) { | ||
| 211 | av_log(avctx, AV_LOG_ERROR, "Command data doesn't fit in frame\n"); | ||
| 212 | return AVERROR_INVALIDDATA; | ||
| 213 | } | ||
| 214 | c->stream += command_size; | ||
| 215 | } | ||
| 216 | if (type & BMV_PALETTE) { | ||
| 217 | if (c->stream - pkt->data > pkt->size - 768) { | ||
| 218 | av_log(avctx, AV_LOG_ERROR, "Palette data doesn't fit in frame\n"); | ||
| 219 | return AVERROR_INVALIDDATA; | ||
| 220 | } | ||
| 221 | for (i = 0; i < 256; i++) | ||
| 222 | c->pal[i] = bytestream_get_be24(&c->stream); | ||
| 223 | } | ||
| 224 | if (type & BMV_SCROLL) { | ||
| 225 | if (c->stream - pkt->data > pkt->size - 2) { | ||
| 226 | av_log(avctx, AV_LOG_ERROR, "Screen offset data doesn't fit in frame\n"); | ||
| 227 | return AVERROR_INVALIDDATA; | ||
| 228 | } | ||
| 229 | scr_off = (int16_t)bytestream_get_le16(&c->stream); | ||
| 230 | } else if ((type & BMV_INTRA) == BMV_INTRA) { | ||
| 231 | scr_off = -640; | ||
| 232 | } else { | ||
| 233 | scr_off = 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | if (decode_bmv_frame(c->stream, pkt->size - (c->stream - pkt->data), c->frame, scr_off)) { | ||
| 237 | av_log(avctx, AV_LOG_ERROR, "Error decoding frame data\n"); | ||
| 238 | return AVERROR_INVALIDDATA; | ||
| 239 | } | ||
| 240 | |||
| 241 | memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE); | ||
| 242 | c->pic.palette_has_changed = type & BMV_PALETTE; | ||
| 243 | |||
| 244 | outptr = c->pic.data[0]; | ||
| 245 | srcptr = c->frame; | ||
| 246 | |||
| 247 | for (i = 0; i < avctx->height; i++) { | ||
| 248 | memcpy(outptr, srcptr, avctx->width); | ||
| 249 | srcptr += avctx->width; | ||
| 250 | outptr += c->pic.linesize[0]; | ||
| 251 | } | ||
| 252 | |||
| 253 | *data_size = sizeof(AVFrame); | ||
| 254 | *(AVFrame*)data = c->pic; | ||
| 255 | |||
| 256 | /* always report that the buffer was completely consumed */ | ||
| 257 | return pkt->size; | ||
| 258 | } | ||
| 259 | |||
| 260 | static av_cold int decode_init(AVCodecContext *avctx) | ||
| 261 | { | ||
| 262 | BMVDecContext * const c = avctx->priv_data; | ||
| 263 | |||
| 264 | c->avctx = avctx; | ||
| 265 | avctx->pix_fmt = PIX_FMT_PAL8; | ||
| 266 | |||
| 267 | c->pic.reference = 1; | ||
| 268 | if (avctx->get_buffer(avctx, &c->pic) < 0) { | ||
| 269 | av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | ||
| 270 | return -1; | ||
| 271 | } | ||
| 272 | |||
| 273 | c->frame = c->frame_base + 640; | ||
| 274 | |||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 278 | static av_cold int decode_end(AVCodecContext *avctx) | ||
| 279 | { | ||
| 280 | BMVDecContext *c = avctx->priv_data; | ||
| 281 | |||
| 282 | if (c->pic.data[0]) | ||
| 283 | avctx->release_buffer(avctx, &c->pic); | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static const int bmv_aud_mults[16] = { | ||
| 289 | 16512, 8256, 4128, 2064, 1032, 516, 258, 192, 129, 88, 64, 56, 48, 40, 36, 32 | ||
| 290 | }; | ||
| 291 | |||
| 292 | static av_cold int bmv_aud_decode_init(AVCodecContext *avctx) | ||
| 293 | { | ||
| 294 | |||
| 295 | if (avctx->channels != 2) { | ||
| 296 | av_log(avctx, AV_LOG_INFO, "invalid number of channels\n"); | ||
| 297 | return AVERROR(EINVAL); | ||
| 298 | } | ||
| 299 | |||
| 300 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; | ||
| 301 | |||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, int *data_size, | ||
| 306 | AVPacket *avpkt) | ||
| 307 | { | ||
| 308 | const uint8_t *buf = avpkt->data; | ||
| 309 | int buf_size = avpkt->size; | ||
| 310 | int blocks = 0, total_blocks, i; | ||
| 311 | int out_size; | ||
| 312 | int16_t *output_samples = data; | ||
| 313 | int scale[2]; | ||
| 314 | |||
| 315 | total_blocks = *buf++; | ||
| 316 | if (buf_size < total_blocks * 65 + 1) { | ||
| 317 | av_log(avctx, AV_LOG_ERROR, "expected %d bytes, got %d\n", | ||
| 318 | total_blocks * 65 + 1, buf_size); | ||
| 319 | return AVERROR_INVALIDDATA; | ||
| 320 | } | ||
| 321 | out_size = total_blocks * 64 * sizeof(*output_samples); | ||
| 322 | if (*data_size < out_size) { | ||
| 323 | av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); | ||
| 324 | return AVERROR(EINVAL); | ||
| 325 | } | ||
| 326 | |||
| 327 | for (blocks = 0; blocks < total_blocks; blocks++) { | ||
| 328 | uint8_t code = *buf++; | ||
| 329 | code = (code >> 1) | (code << 7); | ||
| 330 | scale[0] = bmv_aud_mults[code & 0xF]; | ||
| 331 | scale[1] = bmv_aud_mults[code >> 4]; | ||
| 332 | for (i = 0; i < 32; i++) { | ||
| 333 | *output_samples++ = av_clip_int16((scale[0] * (int8_t)*buf++) >> 5); | ||
| 334 | *output_samples++ = av_clip_int16((scale[1] * (int8_t)*buf++) >> 5); | ||
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | *data_size = out_size; | ||
| 339 | return buf_size; | ||
| 340 | } | ||
| 341 | |||
| 342 | AVCodec ff_bmv_video_decoder = { | ||
| 343 | .name = "bmv_video", | ||
| 344 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 345 | .id = CODEC_ID_BMV_VIDEO, | ||
| 346 | .priv_data_size = sizeof(BMVDecContext), | ||
| 347 | .init = decode_init, | ||
| 348 | .close = decode_end, | ||
| 349 | .decode = decode_frame, | ||
| 350 | .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), | ||
| 351 | }; | ||
| 352 | |||
| 353 | AVCodec ff_bmv_audio_decoder = { | ||
| 354 | .name = "bmv_audio", | ||
| 355 | .type = AVMEDIA_TYPE_AUDIO, | ||
| 356 | .id = CODEC_ID_BMV_AUDIO, | ||
| 357 | .init = bmv_aud_decode_init, | ||
| 358 | .decode = bmv_aud_decode_frame, | ||
| 359 | .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), | ||
| 360 | }; | ||
| @@ -21,7 +21,7 @@ · 20 unmodified lines | |||
| 21 | #define AVCODEC_VERSION_H | 21 | #define AVCODEC_VERSION_H |
| 22 | 22 | ||
| 23 | #define LIBAVCODEC_VERSION_MAJOR 53 | 23 | #define LIBAVCODEC_VERSION_MAJOR 53 |
| 24 | #define LIBAVCODEC_VERSION_MINOR 16 | 24 | #define LIBAVCODEC_VERSION_MINOR 17 |
| 25 | #define LIBAVCODEC_VERSION_MICRO 0 | 25 | #define LIBAVCODEC_VERSION_MICRO 0 |
| 26 | 26 | ||
| 27 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | 27 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| @@ -46,6 +46,7 @@ OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o · 45 unmodified lines | |||
| 46 | OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o | 46 | OBJS-$(CONFIG_BETHSOFTVID_DEMUXER) += bethsoftvid.o |
| 47 | OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o | 47 | OBJS-$(CONFIG_BFI_DEMUXER) += bfi.o |
| 48 | OBJS-$(CONFIG_BINK_DEMUXER) += bink.o | 48 | OBJS-$(CONFIG_BINK_DEMUXER) += bink.o |
| 49 | OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o | ||
| 49 | OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o | 50 | OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o |
| 50 | OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o riff.o isom.o | 51 | OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o riff.o isom.o |
| 51 | OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o | 52 | OBJS-$(CONFIG_CAVSVIDEO_DEMUXER) += cavsvideodec.o rawdec.o |
| @@ -70,6 +70,7 @@ void av_register_all(void) · 69 unmodified lines | |||
| 70 | REGISTER_DEMUXER (BETHSOFTVID, bethsoftvid); | 70 | REGISTER_DEMUXER (BETHSOFTVID, bethsoftvid); |
| 71 | REGISTER_DEMUXER (BFI, bfi); | 71 | REGISTER_DEMUXER (BFI, bfi); |
| 72 | REGISTER_DEMUXER (BINK, bink); | 72 | REGISTER_DEMUXER (BINK, bink); |
| 73 | REGISTER_DEMUXER (BMV, bmv); | ||
| 73 | REGISTER_DEMUXER (C93, c93); | 74 | REGISTER_DEMUXER (C93, c93); |
| 74 | REGISTER_DEMUXER (CAF, caf); | 75 | REGISTER_DEMUXER (CAF, caf); |
| 75 | REGISTER_MUXDEMUX (CAVSVIDEO, cavsvideo); | 76 | REGISTER_MUXDEMUX (CAVSVIDEO, cavsvideo); |
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * Discworld II BMV demuxer | ||
| 3 | * Copyright (c) 2011 Konstantin Shishkov. | ||
| 4 | * | ||
| 5 | * This file is part of Libav. | ||
| 6 | * | ||
| 7 | * Libav is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * Libav is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with Libav; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "avformat.h" | ||
| 23 | |||
| 24 | enum BMVFlags { | ||
| 25 | BMV_NOP = 0, | ||
| 26 | BMV_END, | ||
| 27 | BMV_DELTA, | ||
| 28 | BMV_INTRA, | ||
| 29 | |||
| 30 | BMV_AUDIO = 0x20, | ||
| 31 | }; | ||
| 32 | |||
| 33 | typedef struct BMVContext { | ||
| 34 | uint8_t *packet; | ||
| 35 | int size; | ||
| 36 | int get_next; | ||
| 37 | int64_t audio_pos; | ||
| 38 | } BMVContext; | ||
| 39 | |||
| 40 | static int bmv_read_header(AVFormatContext *s, AVFormatParameters *ap) | ||
| 41 | { | ||
| 42 | AVStream *st, *ast; | ||
| 43 | BMVContext *c = s->priv_data; | ||
| 44 | |||
| 45 | st = avformat_new_stream(s, 0); | ||
| 46 | if (!st) | ||
| 47 | return AVERROR(ENOMEM); | ||
| 48 | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | ||
| 49 | st->codec->codec_id = CODEC_ID_BMV_VIDEO; | ||
| 50 | st->codec->width = 640; | ||
| 51 | st->codec->height = 429; | ||
| 52 | st->codec->pix_fmt = PIX_FMT_PAL8; | ||
| 53 | av_set_pts_info(st, 16, 1, 12); | ||
| 54 | ast = avformat_new_stream(s, 0); | ||
| 55 | if (!ast) | ||
| 56 | return AVERROR(ENOMEM); | ||
| 57 | ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; | ||
| 58 | ast->codec->codec_id = CODEC_ID_BMV_AUDIO; | ||
| 59 | ast->codec->channels = 2; | ||
| 60 | ast->codec->sample_rate = 22050; | ||
| 61 | av_set_pts_info(ast, 16, 1, 22050); | ||
| 62 | |||
| 63 | c->get_next = 1; | ||
| 64 | c->audio_pos = 0; | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static int bmv_read_packet(AVFormatContext *s, AVPacket *pkt) | ||
| 69 | { | ||
| 70 | BMVContext *c = s->priv_data; | ||
| 71 | int type; | ||
| 72 | void *tmp; | ||
| 73 | |||
| 74 | while (c->get_next) { | ||
| 75 | if (s->pb->eof_reached) | ||
| 76 | return AVERROR_EOF; | ||
| 77 | type = avio_r8(s->pb); | ||
| 78 | if (type == BMV_NOP) | ||
| 79 | continue; | ||
| 80 | if (type == BMV_END) | ||
| 81 | return AVERROR_EOF; | ||
| 82 | c->size = avio_rl24(s->pb); | ||
| 83 | if (!c->size) | ||
| 84 | return AVERROR_INVALIDDATA; | ||
| 85 | tmp = av_realloc(c->packet, c->size + 1); | ||
| 86 | if (!tmp) | ||
| 87 | return AVERROR(ENOMEM); | ||
| 88 | c->packet = tmp; | ||
| 89 | c->packet[0] = type; | ||
| 90 | if (avio_read(s->pb, c->packet + 1, c->size) != c->size) | ||
| 91 | return AVERROR(EIO); | ||
| 92 | if (type & BMV_AUDIO) { | ||
| 93 | int audio_size = c->packet[1] * 65 + 1; | ||
| 94 | if (audio_size >= c->size) { | ||
| 95 | av_log(s, AV_LOG_ERROR, "Reported audio size %d is bigger than packet size (%d)\n", | ||
| 96 | audio_size, c->size); | ||
| 97 | return AVERROR_INVALIDDATA; | ||
| 98 | } | ||
| 99 | if (av_new_packet(pkt, audio_size) < 0) | ||
| 100 | return AVERROR(ENOMEM); | ||
| 101 | memcpy(pkt->data, c->packet + 1, pkt->size); | ||
| 102 | pkt->stream_index = 1; | ||
| 103 | pkt->pts = c->audio_pos; | ||
| 104 | pkt->duration = c->packet[1] * 32; | ||
| 105 | c->audio_pos += pkt->duration; | ||
| 106 | c->get_next = 0; | ||
| 107 | return pkt->size; | ||
| 108 | } else | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | if (av_new_packet(pkt, c->size + 1) < 0) | ||
| 112 | return AVERROR(ENOMEM); | ||
| 113 | pkt->stream_index = 0; | ||
| 114 | c->get_next = 1; | ||
| 115 | memcpy(pkt->data, c->packet, pkt->size); | ||
| 116 | return pkt->size; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int bmv_read_close(AVFormatContext *s) | ||
| 120 | { | ||
| 121 | BMVContext *c = s->priv_data; | ||
| 122 | |||
| 123 | av_freep(&c->packet); | ||
| 124 | |||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | AVInputFormat ff_bmv_demuxer = { | ||
| 129 | .name = "bmv", | ||
| 130 | .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV"), | ||
| 131 | .priv_data_size = sizeof(BMVContext), | ||
| 132 | .read_header = bmv_read_header, | ||
| 133 | .read_packet = bmv_read_packet, | ||
| 134 | .read_close = bmv_read_close, | ||
| 135 | .extensions = "bmv" | ||
| 136 | }; | ||
| @@ -24,7 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include "libavutil/avutil.h" | 24 | #include "libavutil/avutil.h" |
| 25 | 25 | ||
| 26 | #define LIBAVFORMAT_VERSION_MAJOR 53 | 26 | #define LIBAVFORMAT_VERSION_MAJOR 53 |
| 27 | #define LIBAVFORMAT_VERSION_MINOR 13 | 27 | #define LIBAVFORMAT_VERSION_MINOR 14 |
| 28 | #define LIBAVFORMAT_VERSION_MICRO 0 | 28 | #define LIBAVFORMAT_VERSION_MICRO 0 |
| 29 | 29 | ||
| 30 | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | 30 | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |