mirror of https://github.com/FFmpeg/FFmpeg.git
courtesy of Konstantin Shishkov Originally committed as revision 3529 to svn://svn.ffmpeg.org/ffmpeg/trunkpull/126/head
parent
98772cbf7b
commit
d08d7142fd
12 changed files with 430 additions and 2 deletions
@ -0,0 +1,153 @@ |
||||
/*
|
||||
* QuickDraw (qdrw) codec |
||||
* Copyright (c) 2004 Konstantin Shishkov |
||||
* |
||||
* This library 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 of the License, or (at your option) any later version. |
||||
* |
||||
* This library 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 this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @file qdrw.c |
||||
* Apple QuickDraw codec. |
||||
*/ |
||||
|
||||
#include "avcodec.h" |
||||
#include "mpegvideo.h" |
||||
|
||||
typedef struct QdrawContext{ |
||||
AVCodecContext *avctx; |
||||
AVFrame pic; |
||||
uint8_t palette[256*3]; |
||||
} QdrawContext; |
||||
|
||||
static int decode_frame(AVCodecContext *avctx,
|
||||
void *data, int *data_size, |
||||
uint8_t *buf, int buf_size) |
||||
{ |
||||
QdrawContext * const a = avctx->priv_data; |
||||
AVFrame * const p= (AVFrame*)&a->pic; |
||||
uint8_t* outdata; |
||||
int colors; |
||||
int i; |
||||
|
||||
/* special case for last picture */ |
||||
if (buf_size == 0) { |
||||
return 0; |
||||
} |
||||
|
||||
if(p->data[0]) |
||||
avctx->release_buffer(avctx, p); |
||||
|
||||
p->reference= 0; |
||||
if(avctx->get_buffer(avctx, p) < 0){ |
||||
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
||||
return -1; |
||||
} |
||||
p->pict_type= I_TYPE; |
||||
p->key_frame= 1; |
||||
|
||||
outdata = a->pic.data[0]; |
||||
|
||||
buf += 0x68; /* jump to palette */ |
||||
colors = BE_32(buf); |
||||
buf += 4; |
||||
|
||||
if(colors < 0 || colors > 256) { |
||||
av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); |
||||
return -1; |
||||
} |
||||
|
||||
for (i = 0; i <= colors; i++) { |
||||
int idx; |
||||
idx = BE_16(buf); /* color index */ |
||||
buf += 2; |
||||
|
||||
a->palette[idx * 3 + 0] = *buf++; |
||||
buf++; |
||||
a->palette[idx * 3 + 1] = *buf++; |
||||
buf++; |
||||
a->palette[idx * 3 + 2] = *buf++; |
||||
buf++; |
||||
} |
||||
|
||||
if (colors) |
||||
a->pic.palette_has_changed = 1; |
||||
|
||||
buf += 18; /* skip unneeded data */ |
||||
for (i = 0; i < avctx->height; i++) { |
||||
int size, left, code, pix; |
||||
uint8_t *next; |
||||
uint8_t *out; |
||||
int tsize = 0; |
||||
|
||||
/* decode line */ |
||||
out = outdata; |
||||
size = BE_16(buf); /* size of packed line */ |
||||
buf += 2; |
||||
left = size; |
||||
next = buf + size; |
||||
while (left > 0) { |
||||
code = *buf++; |
||||
if (code & 0x80 ) { /* run */ |
||||
int i; |
||||
pix = *buf++; |
||||
for (i = 0; i < 257 - code; i++) { |
||||
*out++ = a->palette[pix * 3 + 0]; |
||||
*out++ = a->palette[pix * 3 + 1]; |
||||
*out++ = a->palette[pix * 3 + 2]; |
||||
} |
||||
tsize += 257 - code; |
||||
left -= 2; |
||||
} else { /* copy */ |
||||
int i, pix; |
||||
for (i = 0; i <= code; i++) { |
||||
pix = *buf++; |
||||
*out++ = a->palette[pix * 3 + 0]; |
||||
*out++ = a->palette[pix * 3 + 1]; |
||||
*out++ = a->palette[pix * 3 + 2]; |
||||
} |
||||
left -= 2 + code; |
||||
tsize += code + 1; |
||||
} |
||||
} |
||||
buf = next; |
||||
outdata += a->pic.linesize[0]; |
||||
} |
||||
|
||||
*data_size = sizeof(AVFrame); |
||||
*(AVFrame*)data = a->pic; |
||||
|
||||
return buf_size; |
||||
} |
||||
|
||||
static int decode_init(AVCodecContext *avctx){ |
||||
// QdrawContext * const a = avctx->priv_data;
|
||||
|
||||
avctx->pix_fmt= PIX_FMT_RGB24; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
AVCodec qdraw_decoder = { |
||||
"qdraw", |
||||
CODEC_TYPE_VIDEO, |
||||
CODEC_ID_QDRAW, |
||||
sizeof(QdrawContext), |
||||
decode_init, |
||||
NULL, |
||||
NULL, |
||||
decode_frame, |
||||
CODEC_CAP_DR1, |
||||
}; |
@ -0,0 +1,166 @@ |
||||
/*
|
||||
* Sierra SOL decoder |
||||
* Copyright Konstantin Shishkov. |
||||
* |
||||
* This library 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 of the License, or (at your option) any later version. |
||||
* |
||||
* This library 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 this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
*/ |
||||
|
||||
/*
|
||||
* Based on documents from Game Audio Player and own research |
||||
*/ |
||||
|
||||
#include "avformat.h" |
||||
#include "avi.h" |
||||
#include "bswap.h" |
||||
|
||||
/* if we don't know the size in advance */ |
||||
#define AU_UNKOWN_SIZE ((uint32_t)(~0)) |
||||
|
||||
static int sol_probe(AVProbeData *p) |
||||
{ |
||||
/* check file header */ |
||||
uint16_t magic; |
||||
if (p->buf_size <= 14) |
||||
return 0; |
||||
magic=le2me_16(*((uint16_t*)p->buf)); |
||||
if ((magic == 0x0B8D || magic == 0x0C0D || magic == 0x0C8D) && |
||||
p->buf[2] == 'S' && p->buf[3] == 'O' && |
||||
p->buf[4] == 'L' && p->buf[5] == 0) |
||||
return AVPROBE_SCORE_MAX; |
||||
else |
||||
return 0; |
||||
} |
||||
|
||||
#define SOL_DPCM 1 |
||||
#define SOL_16BIT 4 |
||||
#define SOL_STEREO 16 |
||||
|
||||
static int sol_codec_id(int magic, int type) |
||||
{ |
||||
if (magic == 0x0B8D) |
||||
{ |
||||
if (type & SOL_DPCM) return CODEC_ID_SOL_DPCM; |
||||
else return CODEC_ID_PCM_U8; |
||||
} |
||||
if (type & SOL_DPCM) |
||||
{ |
||||
if (type & SOL_16BIT) return CODEC_ID_SOL_DPCM; |
||||
else if (magic == 0x0C8D) return CODEC_ID_SOL_DPCM; |
||||
else return CODEC_ID_SOL_DPCM; |
||||
} |
||||
if (type & SOL_16BIT) return CODEC_ID_PCM_S16LE; |
||||
return CODEC_ID_PCM_U8; |
||||
} |
||||
|
||||
static int sol_codec_type(int magic, int type) |
||||
{ |
||||
if (magic == 0x0B8D) return 1;//SOL_DPCM_OLD;
|
||||
if (type & SOL_DPCM) |
||||
{ |
||||
if (type & SOL_16BIT) return 3;//SOL_DPCM_NEW16;
|
||||
else if (magic == 0x0C8D) return 1;//SOL_DPCM_OLD;
|
||||
else return 2;//SOL_DPCM_NEW8;
|
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
static int sol_channels(int magic, int type) |
||||
{ |
||||
if (magic == 0x0B8D || !(type & SOL_STEREO)) return 1; |
||||
return 2; |
||||
} |
||||
|
||||
static int sol_read_header(AVFormatContext *s, |
||||
AVFormatParameters *ap) |
||||
{ |
||||
int size; |
||||
unsigned int magic,tag; |
||||
ByteIOContext *pb = &s->pb; |
||||
unsigned int id, codec, channels, rate, type; |
||||
AVStream *st; |
||||
|
||||
/* check ".snd" header */ |
||||
magic = get_le16(pb); |
||||
tag = get_le32(pb); |
||||
if (tag != MKTAG('S', 'O', 'L', 0)) |
||||
return -1; |
||||
rate = get_le16(pb); |
||||
type = get_byte(pb); |
||||
size = get_le32(pb); |
||||
if (magic != 0x0B8D) |
||||
get_byte(pb); /* newer SOLs contain padding byte */ |
||||
|
||||
codec = sol_codec_id(magic, type); |
||||
channels = sol_channels(magic, type); |
||||
|
||||
if (codec == CODEC_ID_SOL_DPCM) |
||||
id = sol_codec_type(magic, type); |
||||
else id = 0; |
||||
|
||||
/* now we are ready: build format streams */ |
||||
st = av_new_stream(s, 0); |
||||
if (!st) |
||||
return -1; |
||||
st->codec.codec_type = CODEC_TYPE_AUDIO; |
||||
st->codec.codec_tag = id; |
||||
st->codec.codec_id = codec; |
||||
st->codec.channels = channels; |
||||
st->codec.sample_rate = rate; |
||||
return 0; |
||||
} |
||||
|
||||
#define MAX_SIZE 4096 |
||||
|
||||
static int sol_read_packet(AVFormatContext *s, |
||||
AVPacket *pkt) |
||||
{ |
||||
int ret; |
||||
|
||||
if (url_feof(&s->pb)) |
||||
return -EIO; |
||||
if (av_new_packet(pkt, MAX_SIZE)) |
||||
return -EIO; |
||||
pkt->stream_index = 0; |
||||
|
||||
ret = get_buffer(&s->pb, pkt->data, pkt->size); |
||||
if (ret < 0) |
||||
av_free_packet(pkt); |
||||
/* note: we need to modify the packet size here to handle the last
|
||||
packet */ |
||||
pkt->size = ret; |
||||
return 0; |
||||
} |
||||
|
||||
static int sol_read_close(AVFormatContext *s) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
static AVInputFormat sol_iformat = { |
||||
"sol", |
||||
"Sierra SOL Format", |
||||
0, |
||||
sol_probe, |
||||
sol_read_header, |
||||
sol_read_packet, |
||||
sol_read_close, |
||||
pcm_read_seek, |
||||
}; |
||||
|
||||
int sol_init(void) |
||||
{ |
||||
av_register_input_format(&sol_iformat); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue