|
|
|
@@ -73,9 +73,6 @@ static int roq_read_header(AVFormatContext *s, |
|
|
|
ByteIOContext *pb = s->pb; |
|
|
|
AVStream *st; |
|
|
|
unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE]; |
|
|
|
int i; |
|
|
|
unsigned int chunk_size; |
|
|
|
unsigned int chunk_type; |
|
|
|
|
|
|
|
/* get the main header */ |
|
|
|
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != |
|
|
|
@@ -87,58 +84,8 @@ static int roq_read_header(AVFormatContext *s, |
|
|
|
/* init private context parameters */ |
|
|
|
roq->width = roq->height = roq->audio_channels = roq->video_pts = |
|
|
|
roq->audio_frame_count = 0; |
|
|
|
roq->audio_stream_index = -1; |
|
|
|
|
|
|
|
/* scan the first n chunks searching for A/V parameters */ |
|
|
|
for (i = 0; i < RoQ_CHUNKS_TO_SCAN; i++) { |
|
|
|
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != |
|
|
|
RoQ_CHUNK_PREAMBLE_SIZE) |
|
|
|
return AVERROR(EIO); |
|
|
|
|
|
|
|
chunk_type = AV_RL16(&preamble[0]); |
|
|
|
chunk_size = AV_RL32(&preamble[2]); |
|
|
|
|
|
|
|
switch (chunk_type) { |
|
|
|
|
|
|
|
case RoQ_INFO: |
|
|
|
/* fetch the width and height; reuse the preamble bytes */ |
|
|
|
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != |
|
|
|
RoQ_CHUNK_PREAMBLE_SIZE) |
|
|
|
return AVERROR(EIO); |
|
|
|
roq->width = AV_RL16(&preamble[0]); |
|
|
|
roq->height = AV_RL16(&preamble[2]); |
|
|
|
break; |
|
|
|
|
|
|
|
case RoQ_QUAD_CODEBOOK: |
|
|
|
case RoQ_QUAD_VQ: |
|
|
|
/* ignore during this scan */ |
|
|
|
url_fseek(pb, chunk_size, SEEK_CUR); |
|
|
|
break; |
|
|
|
|
|
|
|
case RoQ_SOUND_MONO: |
|
|
|
roq->audio_channels = 1; |
|
|
|
url_fseek(pb, chunk_size, SEEK_CUR); |
|
|
|
break; |
|
|
|
|
|
|
|
case RoQ_SOUND_STEREO: |
|
|
|
roq->audio_channels = 2; |
|
|
|
url_fseek(pb, chunk_size, SEEK_CUR); |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
av_log(s, AV_LOG_ERROR, " unknown RoQ chunk type (%04X)\n", AV_RL16(&preamble[0])); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* if all necessary parameters have been gathered, exit early */ |
|
|
|
if ((roq->width && roq->height) && roq->audio_channels) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* seek back to the first chunk */ |
|
|
|
url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_SET); |
|
|
|
|
|
|
|
/* initialize the decoders */ |
|
|
|
st = av_new_stream(s, 0); |
|
|
|
if (!st) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
@@ -148,25 +95,6 @@ static int roq_read_header(AVFormatContext *s, |
|
|
|
st->codec->codec_type = CODEC_TYPE_VIDEO; |
|
|
|
st->codec->codec_id = CODEC_ID_ROQ; |
|
|
|
st->codec->codec_tag = 0; /* no fourcc */ |
|
|
|
st->codec->width = roq->width; |
|
|
|
st->codec->height = roq->height; |
|
|
|
|
|
|
|
if (roq->audio_channels) { |
|
|
|
st = av_new_stream(s, 0); |
|
|
|
if (!st) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
av_set_pts_info(st, 33, 1, 90000); |
|
|
|
roq->audio_stream_index = st->index; |
|
|
|
st->codec->codec_type = CODEC_TYPE_AUDIO; |
|
|
|
st->codec->codec_id = CODEC_ID_ROQ_DPCM; |
|
|
|
st->codec->codec_tag = 0; /* no tag */ |
|
|
|
st->codec->channels = roq->audio_channels; |
|
|
|
st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE; |
|
|
|
st->codec->bits_per_coded_sample = 16; |
|
|
|
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * |
|
|
|
st->codec->bits_per_coded_sample; |
|
|
|
st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
@@ -202,6 +130,14 @@ static int roq_read_packet(AVFormatContext *s, |
|
|
|
switch (chunk_type) { |
|
|
|
|
|
|
|
case RoQ_INFO: |
|
|
|
if (!roq->width || !roq->height) { |
|
|
|
AVStream *st = s->streams[roq->video_stream_index]; |
|
|
|
if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) |
|
|
|
return AVERROR(EIO); |
|
|
|
st->codec->width = roq->width = AV_RL16(preamble); |
|
|
|
st->codec->height = roq->height = AV_RL16(preamble + 2); |
|
|
|
break; |
|
|
|
} |
|
|
|
/* don't care about this chunk anymore */ |
|
|
|
url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR); |
|
|
|
break; |
|
|
|
@@ -233,6 +169,22 @@ static int roq_read_packet(AVFormatContext *s, |
|
|
|
|
|
|
|
case RoQ_SOUND_MONO: |
|
|
|
case RoQ_SOUND_STEREO: |
|
|
|
if (roq->audio_stream_index == -1) { |
|
|
|
AVStream *st = av_new_stream(s, 1); |
|
|
|
if (!st) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
av_set_pts_info(st, 33, 1, 90000); |
|
|
|
roq->audio_stream_index = st->index; |
|
|
|
st->codec->codec_type = CODEC_TYPE_AUDIO; |
|
|
|
st->codec->codec_id = CODEC_ID_ROQ_DPCM; |
|
|
|
st->codec->codec_tag = 0; /* no tag */ |
|
|
|
st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1; |
|
|
|
st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE; |
|
|
|
st->codec->bits_per_coded_sample = 16; |
|
|
|
st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * |
|
|
|
st->codec->bits_per_coded_sample; |
|
|
|
st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; |
|
|
|
} |
|
|
|
case RoQ_QUAD_VQ: |
|
|
|
/* load up the packet */ |
|
|
|
if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE)) |
|
|
|
|