mirror of https://git.ffmpeg.org/ffmpeg.git
avformat/pp_bnk: treat music files as stereo
These files are technically a series of planar mono tracks. If the "music" flag is set, merge the packets from the two mono tracks, essentially replicating: [0🅰️0][0🅰️1]join=inputs=2:channel_layout=stereo[a] Signed-off-by: Zane van Iperen <zane@zanevaniperen.com>
This commit is contained in:
parent
d294c33231
commit
6973df1122
|
@ -55,6 +55,7 @@ typedef struct PPBnkCtx {
|
||||||
int track_count;
|
int track_count;
|
||||||
PPBnkCtxTrack *tracks;
|
PPBnkCtxTrack *tracks;
|
||||||
uint32_t current_track;
|
uint32_t current_track;
|
||||||
|
int is_music;
|
||||||
} PPBnkCtx;
|
} PPBnkCtx;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -194,8 +195,12 @@ static int pp_bnk_read_header(AVFormatContext *s)
|
||||||
goto fail;
|
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. */
|
/* 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))) {
|
if (!(st = avformat_new_stream(s, NULL))) {
|
||||||
ret = AVERROR(ENOMEM);
|
ret = AVERROR(ENOMEM);
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -204,14 +209,21 @@ static int pp_bnk_read_header(AVFormatContext *s)
|
||||||
par = st->codecpar;
|
par = st->codecpar;
|
||||||
par->codec_type = AVMEDIA_TYPE_AUDIO;
|
par->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING;
|
par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING;
|
||||||
par->format = AV_SAMPLE_FMT_S16;
|
par->format = AV_SAMPLE_FMT_S16P;
|
||||||
par->channel_layout = AV_CH_LAYOUT_MONO;
|
|
||||||
par->channels = 1;
|
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->sample_rate = hdr.sample_rate;
|
||||||
par->bits_per_coded_sample = 4;
|
par->bits_per_coded_sample = 4;
|
||||||
par->bits_per_raw_sample = 16;
|
par->bits_per_raw_sample = 16;
|
||||||
par->block_align = 1;
|
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);
|
avpriv_set_pts_info(st, 64, 1, par->sample_rate);
|
||||||
st->start_time = 0;
|
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);
|
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. */
|
/* If we've hit EOF, don't attempt this track again. */
|
||||||
trk->data_size = trk->bytes_read;
|
trk->data_size = trk->bytes_read;
|
||||||
continue;
|
continue;
|
||||||
|
@ -263,8 +290,19 @@ static int pp_bnk_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
|
|
||||||
trk->bytes_read += ret;
|
trk->bytes_read += ret;
|
||||||
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
|
pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
|
||||||
pkt->stream_index = ctx->current_track++;
|
pkt->stream_index = ctx->current_track;
|
||||||
pkt->duration = ret * 2;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue