|
|
|
@@ -55,6 +55,7 @@ typedef struct PPBnkCtx { |
|
|
|
int track_count; |
|
|
|
PPBnkCtxTrack *tracks; |
|
|
|
uint32_t current_track; |
|
|
|
int is_music; |
|
|
|
} PPBnkCtx; |
|
|
|
|
|
|
|
enum { |
|
|
|
@@ -194,8 +195,12 @@ static int pp_bnk_read_header(AVFormatContext *s) |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
ctx->is_music = (hdr.flags & PP_BNK_FLAG_MUSIC) && |
|
|
|
(ctx->track_count == 2) && |
|
|
|
(ctx->tracks[0].data_size == ctx->tracks[1].data_size); |
|
|
|
|
|
|
|
/* Build the streams. */ |
|
|
|
for (int i = 0; i < ctx->track_count; i++) { |
|
|
|
for (int i = 0; i < (ctx->is_music ? 1 : ctx->track_count); i++) { |
|
|
|
if (!(st = avformat_new_stream(s, NULL))) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto fail; |
|
|
|
@@ -204,14 +209,21 @@ static int pp_bnk_read_header(AVFormatContext *s) |
|
|
|
par = st->codecpar; |
|
|
|
par->codec_type = AVMEDIA_TYPE_AUDIO; |
|
|
|
par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING; |
|
|
|
par->format = AV_SAMPLE_FMT_S16; |
|
|
|
par->channel_layout = AV_CH_LAYOUT_MONO; |
|
|
|
par->channels = 1; |
|
|
|
par->format = AV_SAMPLE_FMT_S16P; |
|
|
|
|
|
|
|
if (ctx->is_music) { |
|
|
|
par->channel_layout = AV_CH_LAYOUT_STEREO; |
|
|
|
par->channels = 2; |
|
|
|
} else { |
|
|
|
par->channel_layout = AV_CH_LAYOUT_MONO; |
|
|
|
par->channels = 1; |
|
|
|
} |
|
|
|
|
|
|
|
par->sample_rate = hdr.sample_rate; |
|
|
|
par->bits_per_coded_sample = 4; |
|
|
|
par->bits_per_raw_sample = 16; |
|
|
|
par->block_align = 1; |
|
|
|
par->bit_rate = par->sample_rate * par->bits_per_coded_sample; |
|
|
|
par->bit_rate = par->sample_rate * par->bits_per_coded_sample * par->channels; |
|
|
|
|
|
|
|
avpriv_set_pts_info(st, 64, 1, par->sample_rate); |
|
|
|
st->start_time = 0; |
|
|
|
@@ -253,7 +265,22 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
|
|
|
size = FFMIN(trk->data_size - trk->bytes_read, PP_BNK_MAX_READ_SIZE); |
|
|
|
|
|
|
|
if ((ret = av_get_packet(s->pb, pkt, size)) == AVERROR_EOF) { |
|
|
|
if (!ctx->is_music) |
|
|
|
ret = av_new_packet(pkt, size); |
|
|
|
else if (ctx->current_track == 0) |
|
|
|
ret = av_new_packet(pkt, size * 2); |
|
|
|
else |
|
|
|
ret = 0; |
|
|
|
|
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
if (ctx->is_music) |
|
|
|
ret = avio_read(s->pb, pkt->data + size * ctx->current_track, size); |
|
|
|
else |
|
|
|
ret = avio_read(s->pb, pkt->data, size); |
|
|
|
|
|
|
|
if (ret == AVERROR_EOF) { |
|
|
|
/* If we've hit EOF, don't attempt this track again. */ |
|
|
|
trk->data_size = trk->bytes_read; |
|
|
|
continue; |
|
|
|
@@ -263,8 +290,19 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
|
|
|
trk->bytes_read += ret; |
|
|
|
pkt->flags &= ~AV_PKT_FLAG_CORRUPT; |
|
|
|
pkt->stream_index = ctx->current_track++; |
|
|
|
pkt->stream_index = ctx->current_track; |
|
|
|
pkt->duration = ret * 2; |
|
|
|
|
|
|
|
if (ctx->is_music) { |
|
|
|
if (pkt->stream_index == 0) |
|
|
|
continue; |
|
|
|
|
|
|
|
pkt->stream_index = 0; |
|
|
|
} else { |
|
|
|
pkt->size = ret; |
|
|
|
} |
|
|
|
|
|
|
|
ctx->current_track++; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|