annotate ffmpeg/libavformat/bethsoftvid.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Bethsoft VID format Demuxer
yading@11 3 * Copyright (c) 2007 Nicholas Tung
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 /**
yading@11 23 * @file
yading@11 24 * @brief Bethesda Softworks VID (.vid) file demuxer
yading@11 25 * @author Nicholas Tung [ntung (at. ntung com] (2007-03)
yading@11 26 * @see http://wiki.multimedia.cx/index.php?title=Bethsoft_VID
yading@11 27 * @see http://www.svatopluk.com/andux/docs/dfvid.html
yading@11 28 */
yading@11 29
yading@11 30 #include "libavutil/channel_layout.h"
yading@11 31 #include "libavutil/intreadwrite.h"
yading@11 32 #include "avformat.h"
yading@11 33 #include "internal.h"
yading@11 34 #include "libavcodec/bethsoftvideo.h"
yading@11 35
yading@11 36 #define BVID_PALETTE_SIZE 3 * 256
yading@11 37
yading@11 38 #define DEFAULT_SAMPLE_RATE 11111
yading@11 39
yading@11 40 typedef struct BVID_DemuxContext
yading@11 41 {
yading@11 42 int nframes;
yading@11 43 int sample_rate; /**< audio sample rate */
yading@11 44 int width; /**< video width */
yading@11 45 int height; /**< video height */
yading@11 46 /** delay value between frames, added to individual frame delay.
yading@11 47 * custom units, which will be added to other custom units (~=16ms according
yading@11 48 * to free, unofficial documentation) */
yading@11 49 int bethsoft_global_delay;
yading@11 50 int video_index; /**< video stream index */
yading@11 51 int audio_index; /**< audio stream index */
yading@11 52 uint8_t *palette;
yading@11 53
yading@11 54 int is_finished;
yading@11 55
yading@11 56 } BVID_DemuxContext;
yading@11 57
yading@11 58 static int vid_probe(AVProbeData *p)
yading@11 59 {
yading@11 60 // little-endian VID tag, file starts with "VID\0"
yading@11 61 if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
yading@11 62 return 0;
yading@11 63
yading@11 64 return AVPROBE_SCORE_MAX;
yading@11 65 }
yading@11 66
yading@11 67 static int vid_read_header(AVFormatContext *s)
yading@11 68 {
yading@11 69 BVID_DemuxContext *vid = s->priv_data;
yading@11 70 AVIOContext *pb = s->pb;
yading@11 71
yading@11 72 /* load main header. Contents:
yading@11 73 * bytes: 'V' 'I' 'D'
yading@11 74 * int16s: always_512, nframes, width, height, delay, always_14
yading@11 75 */
yading@11 76 avio_skip(pb, 5);
yading@11 77 vid->nframes = avio_rl16(pb);
yading@11 78 vid->width = avio_rl16(pb);
yading@11 79 vid->height = avio_rl16(pb);
yading@11 80 vid->bethsoft_global_delay = avio_rl16(pb);
yading@11 81 avio_rl16(pb);
yading@11 82
yading@11 83 // wait until the first packet to create each stream
yading@11 84 vid->video_index = -1;
yading@11 85 vid->audio_index = -1;
yading@11 86 vid->sample_rate = DEFAULT_SAMPLE_RATE;
yading@11 87 s->ctx_flags |= AVFMTCTX_NOHEADER;
yading@11 88
yading@11 89 return 0;
yading@11 90 }
yading@11 91
yading@11 92 #define BUFFER_PADDING_SIZE 1000
yading@11 93 static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt,
yading@11 94 uint8_t block_type, AVFormatContext *s)
yading@11 95 {
yading@11 96 uint8_t * vidbuf_start = NULL;
yading@11 97 int vidbuf_nbytes = 0;
yading@11 98 int code;
yading@11 99 int bytes_copied = 0;
yading@11 100 int position, duration, npixels;
yading@11 101 unsigned int vidbuf_capacity;
yading@11 102 int ret = 0;
yading@11 103 AVStream *st;
yading@11 104
yading@11 105 if (vid->video_index < 0) {
yading@11 106 st = avformat_new_stream(s, NULL);
yading@11 107 if (!st)
yading@11 108 return AVERROR(ENOMEM);
yading@11 109 vid->video_index = st->index;
yading@11 110 if (vid->audio_index < 0) {
yading@11 111 avpriv_request_sample(s, "Using default video time base since "
yading@11 112 "having no audio packet before the first "
yading@11 113 "video packet");
yading@11 114 }
yading@11 115 avpriv_set_pts_info(st, 64, 185, vid->sample_rate);
yading@11 116 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 117 st->codec->codec_id = AV_CODEC_ID_BETHSOFTVID;
yading@11 118 st->codec->width = vid->width;
yading@11 119 st->codec->height = vid->height;
yading@11 120 }
yading@11 121 st = s->streams[vid->video_index];
yading@11 122 npixels = st->codec->width * st->codec->height;
yading@11 123
yading@11 124 vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE);
yading@11 125 if(!vidbuf_start)
yading@11 126 return AVERROR(ENOMEM);
yading@11 127
yading@11 128 // save the file position for the packet, include block type
yading@11 129 position = avio_tell(pb) - 1;
yading@11 130
yading@11 131 vidbuf_start[vidbuf_nbytes++] = block_type;
yading@11 132
yading@11 133 // get the current packet duration
yading@11 134 duration = vid->bethsoft_global_delay + avio_rl16(pb);
yading@11 135
yading@11 136 // set the y offset if it exists (decoder header data should be in data section)
yading@11 137 if(block_type == VIDEO_YOFF_P_FRAME){
yading@11 138 if (avio_read(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2) {
yading@11 139 ret = AVERROR(EIO);
yading@11 140 goto fail;
yading@11 141 }
yading@11 142 vidbuf_nbytes += 2;
yading@11 143 }
yading@11 144
yading@11 145 do{
yading@11 146 vidbuf_start = av_fast_realloc(vidbuf_start, &vidbuf_capacity, vidbuf_nbytes + BUFFER_PADDING_SIZE);
yading@11 147 if(!vidbuf_start)
yading@11 148 return AVERROR(ENOMEM);
yading@11 149
yading@11 150 code = avio_r8(pb);
yading@11 151 vidbuf_start[vidbuf_nbytes++] = code;
yading@11 152
yading@11 153 if(code >= 0x80){ // rle sequence
yading@11 154 if(block_type == VIDEO_I_FRAME)
yading@11 155 vidbuf_start[vidbuf_nbytes++] = avio_r8(pb);
yading@11 156 } else if(code){ // plain sequence
yading@11 157 if (avio_read(pb, &vidbuf_start[vidbuf_nbytes], code) != code) {
yading@11 158 ret = AVERROR(EIO);
yading@11 159 goto fail;
yading@11 160 }
yading@11 161 vidbuf_nbytes += code;
yading@11 162 }
yading@11 163 bytes_copied += code & 0x7F;
yading@11 164 if(bytes_copied == npixels){ // sometimes no stop character is given, need to keep track of bytes copied
yading@11 165 // may contain a 0 byte even if read all pixels
yading@11 166 if(avio_r8(pb))
yading@11 167 avio_seek(pb, -1, SEEK_CUR);
yading@11 168 break;
yading@11 169 }
yading@11 170 if (bytes_copied > npixels) {
yading@11 171 ret = AVERROR_INVALIDDATA;
yading@11 172 goto fail;
yading@11 173 }
yading@11 174 } while(code);
yading@11 175
yading@11 176 // copy data into packet
yading@11 177 if ((ret = av_new_packet(pkt, vidbuf_nbytes)) < 0)
yading@11 178 goto fail;
yading@11 179 memcpy(pkt->data, vidbuf_start, vidbuf_nbytes);
yading@11 180 av_free(vidbuf_start);
yading@11 181
yading@11 182 pkt->pos = position;
yading@11 183 pkt->stream_index = vid->video_index;
yading@11 184 pkt->duration = duration;
yading@11 185 if (block_type == VIDEO_I_FRAME)
yading@11 186 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 187
yading@11 188 /* if there is a new palette available, add it to packet side data */
yading@11 189 if (vid->palette) {
yading@11 190 uint8_t *pdata = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
yading@11 191 BVID_PALETTE_SIZE);
yading@11 192 if (pdata)
yading@11 193 memcpy(pdata, vid->palette, BVID_PALETTE_SIZE);
yading@11 194 av_freep(&vid->palette);
yading@11 195 }
yading@11 196
yading@11 197 vid->nframes--; // used to check if all the frames were read
yading@11 198 return 0;
yading@11 199 fail:
yading@11 200 av_free(vidbuf_start);
yading@11 201 return ret;
yading@11 202 }
yading@11 203
yading@11 204 static int vid_read_packet(AVFormatContext *s,
yading@11 205 AVPacket *pkt)
yading@11 206 {
yading@11 207 BVID_DemuxContext *vid = s->priv_data;
yading@11 208 AVIOContext *pb = s->pb;
yading@11 209 unsigned char block_type;
yading@11 210 int audio_length;
yading@11 211 int ret_value;
yading@11 212
yading@11 213 if(vid->is_finished || url_feof(pb))
yading@11 214 return AVERROR_EOF;
yading@11 215
yading@11 216 block_type = avio_r8(pb);
yading@11 217 switch(block_type){
yading@11 218 case PALETTE_BLOCK:
yading@11 219 if (vid->palette) {
yading@11 220 av_log(s, AV_LOG_WARNING, "discarding unused palette\n");
yading@11 221 av_freep(&vid->palette);
yading@11 222 }
yading@11 223 vid->palette = av_malloc(BVID_PALETTE_SIZE);
yading@11 224 if (!vid->palette)
yading@11 225 return AVERROR(ENOMEM);
yading@11 226 if (avio_read(pb, vid->palette, BVID_PALETTE_SIZE) != BVID_PALETTE_SIZE) {
yading@11 227 av_freep(&vid->palette);
yading@11 228 return AVERROR(EIO);
yading@11 229 }
yading@11 230 return vid_read_packet(s, pkt);
yading@11 231
yading@11 232 case FIRST_AUDIO_BLOCK:
yading@11 233 avio_rl16(pb);
yading@11 234 // soundblaster DAC used for sample rate, as on specification page (link above)
yading@11 235 vid->sample_rate = 1000000 / (256 - avio_r8(pb));
yading@11 236 case AUDIO_BLOCK:
yading@11 237 if (vid->audio_index < 0) {
yading@11 238 AVStream *st = avformat_new_stream(s, NULL);
yading@11 239 if (!st)
yading@11 240 return AVERROR(ENOMEM);
yading@11 241 vid->audio_index = st->index;
yading@11 242 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@11 243 st->codec->codec_id = AV_CODEC_ID_PCM_U8;
yading@11 244 st->codec->channels = 1;
yading@11 245 st->codec->channel_layout = AV_CH_LAYOUT_MONO;
yading@11 246 st->codec->bits_per_coded_sample = 8;
yading@11 247 st->codec->sample_rate = vid->sample_rate;
yading@11 248 st->codec->bit_rate = 8 * st->codec->sample_rate;
yading@11 249 st->start_time = 0;
yading@11 250 avpriv_set_pts_info(st, 64, 1, vid->sample_rate);
yading@11 251 }
yading@11 252 audio_length = avio_rl16(pb);
yading@11 253 if ((ret_value = av_get_packet(pb, pkt, audio_length)) != audio_length) {
yading@11 254 if (ret_value < 0)
yading@11 255 return ret_value;
yading@11 256 av_log(s, AV_LOG_ERROR, "incomplete audio block\n");
yading@11 257 return AVERROR(EIO);
yading@11 258 }
yading@11 259 pkt->stream_index = vid->audio_index;
yading@11 260 pkt->duration = audio_length;
yading@11 261 pkt->flags |= AV_PKT_FLAG_KEY;
yading@11 262 return 0;
yading@11 263
yading@11 264 case VIDEO_P_FRAME:
yading@11 265 case VIDEO_YOFF_P_FRAME:
yading@11 266 case VIDEO_I_FRAME:
yading@11 267 return read_frame(vid, pb, pkt, block_type, s);
yading@11 268
yading@11 269 case EOF_BLOCK:
yading@11 270 if(vid->nframes != 0)
yading@11 271 av_log(s, AV_LOG_VERBOSE, "reached terminating character but not all frames read.\n");
yading@11 272 vid->is_finished = 1;
yading@11 273 return AVERROR(EIO);
yading@11 274 default:
yading@11 275 av_log(s, AV_LOG_ERROR, "unknown block (character = %c, decimal = %d, hex = %x)!!!\n",
yading@11 276 block_type, block_type, block_type);
yading@11 277 return AVERROR_INVALIDDATA;
yading@11 278 }
yading@11 279 }
yading@11 280
yading@11 281 static int vid_read_close(AVFormatContext *s)
yading@11 282 {
yading@11 283 BVID_DemuxContext *vid = s->priv_data;
yading@11 284 av_freep(&vid->palette);
yading@11 285 return 0;
yading@11 286 }
yading@11 287
yading@11 288 AVInputFormat ff_bethsoftvid_demuxer = {
yading@11 289 .name = "bethsoftvid",
yading@11 290 .long_name = NULL_IF_CONFIG_SMALL("Bethesda Softworks VID"),
yading@11 291 .priv_data_size = sizeof(BVID_DemuxContext),
yading@11 292 .read_probe = vid_probe,
yading@11 293 .read_header = vid_read_header,
yading@11 294 .read_packet = vid_read_packet,
yading@11 295 .read_close = vid_read_close,
yading@11 296 };