/** video presentation time stamp.
* delay = 16 milliseconds * (global_delay + per_frame_delay) */
- int64_t video_pts;
+ int video_pts;
int is_finished;
static int vid_probe(AVProbeData *p)
{
// little endian VID tag, file starts with "VID\0"
- if (p->buf_size < 4 || AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
+ if (AV_RL32(p->buf) != MKTAG('V', 'I', 'D', 0))
return 0;
return AVPROBE_SCORE_MAX;
static int vid_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
- BVID_DemuxContext *vid = s->priv_data; // permanent data outside of function
- ByteIOContext *pb = &s->pb; // io to file
+ BVID_DemuxContext *vid = s->priv_data;
+ ByteIOContext *pb = &s->pb;
AVStream *stream;
/* load main header. Contents:
url_fseek(pb, 5, SEEK_CUR);
vid->nframes = get_le16(pb);
- // FFmpeg central code will use this; don't need to return or anything
- // initialize the bethsoft codec
stream = av_new_stream(s, 0);
if (!stream)
return AVERROR_NOMEM;
{
uint8_t * vidbuf_start = NULL;
int vidbuf_nbytes = 0;
- int rle_num_bytes;
+ int code;
int bytes_copied = 0;
int position;
size_t vidbuf_capacity;
// save the file position for the packet, include block type
position = url_ftell(pb) - 1;
- // set the block type for the decoder
vidbuf_start[vidbuf_nbytes++] = block_type;
// get the video delay (next int16), and set the presentation time
vid->video_pts += vid->bethsoft_global_delay + get_le16(pb);
// set the y offset if it exists (decoder header data should be in data section)
- if(block_type == VIDEO_YOFFSET_DIFFERENCE_FRAME_BLOCK){
+ if(block_type == VIDEO_YOFF_P_FRAME){
if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], 2) != 2)
goto fail;
vidbuf_nbytes += 2;
if(!vidbuf_start)
return AVERROR_NOMEM;
- rle_num_bytes = get_byte(pb);
- vidbuf_start[vidbuf_nbytes++] = rle_num_bytes;
+ code = get_byte(pb);
+ vidbuf_start[vidbuf_nbytes++] = code;
- if(rle_num_bytes > 0x80){ // rle sequence
- if(block_type == VIDEO_FULL_FRAME_BLOCK)
+ if(code >= 0x80){ // rle sequence
+ if(block_type == VIDEO_I_FRAME)
vidbuf_start[vidbuf_nbytes++] = get_byte(pb);
- bytes_copied += rle_num_bytes - 0x80;
- } else if(rle_num_bytes){ // plain sequence
- if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], rle_num_bytes) != rle_num_bytes)
+ } else if(code){ // plain sequence
+ if(get_buffer(pb, &vidbuf_start[vidbuf_nbytes], code) != code)
goto fail;
- vidbuf_nbytes += rle_num_bytes;
- bytes_copied += rle_num_bytes;
+ vidbuf_nbytes += code;
}
+ bytes_copied += code & 0x7F;
if(bytes_copied == npixels){ // sometimes no stop character is given, need to keep track of bytes copied
// may contain a 0 byte even if read all pixels
if(get_byte(pb))
}
if(bytes_copied > npixels)
goto fail;
- } while(rle_num_bytes);
+ } while(code);
// copy data into packet
if(av_new_packet(pkt, vidbuf_nbytes) < 0)
static int vid_read_packet(AVFormatContext *s,
AVPacket *pkt)
{
- BVID_DemuxContext *vid = s->priv_data; // permanent data outside of function
- ByteIOContext *pb = &s->pb; // io to file
- unsigned char block_type; // block type
+ BVID_DemuxContext *vid = s->priv_data;
+ ByteIOContext *pb = &s->pb;
+ unsigned char block_type;
int audio_length;
int ret_value;
- av_log(s, AV_LOG_DEBUG, "[bethsoftvid demuxer read_packet]");
-
if(vid->is_finished || url_feof(pb))
return AVERROR_IO;
block_type = get_byte(pb);
switch(block_type){
case PALETTE_BLOCK:
- av_log(s, AV_LOG_DEBUG, "palette block.\n");
url_fseek(pb, -1, SEEK_CUR); // include block type
- ret_value = av_get_packet(pb, pkt, 3 * VID_PALETTE_NUMCOLORS + 1);
- if(ret_value != 3 * VID_PALETTE_NUMCOLORS + 1){
+ ret_value = av_get_packet(pb, pkt, 3 * 256 + 1);
+ if(ret_value != 3 * 256 + 1){
av_free_packet(pkt);
return AVERROR_IO;
}
return ret_value;
case FIRST_AUDIO_BLOCK:
- av_log(s, AV_LOG_DEBUG, "first ");
- get_le16(pb); // some unused constant
+ get_le16(pb);
// soundblaster DAC used for sample rate, as on specification page (link above)
s->streams[1]->codec->sample_rate = 1000000 / (256 - get_byte(pb));
s->streams[1]->codec->bit_rate = s->streams[1]->codec->channels * s->streams[1]->codec->sample_rate * s->streams[1]->codec->bits_per_sample;
case AUDIO_BLOCK:
- av_log(s, AV_LOG_DEBUG, "audio block.\n");
audio_length = get_le16(pb);
ret_value = av_get_packet(pb, pkt, audio_length);
pkt->stream_index = 1;
return (ret_value != audio_length ? AVERROR_IO : ret_value);
- case VIDEO_DIFFERENCE_FRAME_BLOCK: av_log(s, AV_LOG_DEBUG, "non-");
- case VIDEO_YOFFSET_DIFFERENCE_FRAME_BLOCK: av_log(s, AV_LOG_DEBUG, "offset ");
- case VIDEO_FULL_FRAME_BLOCK: av_log(s, AV_LOG_DEBUG, "video block.\n");
+ case VIDEO_P_FRAME:
+ case VIDEO_YOFF_P_FRAME:
+ case VIDEO_I_FRAME:
return read_frame(vid, pb, pkt, block_type, s,
s->streams[0]->codec->width * s->streams[0]->codec->height);
- case FINISHED_BLOCK:
+ case EOF_BLOCK:
if(vid->nframes != 0)
av_log(s, AV_LOG_VERBOSE, "reached terminating character but not all frames read.\n");
vid->is_finished = 1;
- av_log(s, AV_LOG_DEBUG, "terminating block.\n");
return AVERROR_IO;
default:
av_log(s, AV_LOG_ERROR, "unknown block (character = %c, decimal = %d, hex = %x)!!!\n",