X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fbink.c;h=b576555debc0b7d4805df654e47dae123cd1f03c;hb=2a44a8f6091913bad14c4df318ceeb68dc4a9258;hp=7d69387deb55773dc4044fa0290a8653968ba878;hpb=971c55f18680020908eeae3972bd20b36921b7e1;p=ffmpeg diff --git a/libavformat/bink.c b/libavformat/bink.c index 7d69387deb5..b576555debc 100644 --- a/libavformat/bink.c +++ b/libavformat/bink.c @@ -3,25 +3,25 @@ * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org) * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav 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.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav 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 FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file libavformat/bink.c + * @file * Bink demuxer * * Technical details here: @@ -44,7 +44,6 @@ enum BinkAudFlags { typedef struct { uint32_t file_size; - uint32_t total_frames; uint32_t num_audio_tracks; int current_track; ///< audio track to return in next packet @@ -71,11 +70,11 @@ static int probe(AVProbeData *p) static int read_header(AVFormatContext *s, AVFormatParameters *ap) { BinkDemuxContext *bink = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; uint32_t fps_num, fps_den; AVStream *vst, *ast; unsigned int i; - uint32_t pos, prev_pos; + uint32_t pos, next_pos; uint16_t flags; int keyframe; @@ -83,40 +82,42 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap) if (!vst) return AVERROR(ENOMEM); - vst->codec->codec_tag = get_le32(pb); + vst->codec->codec_tag = avio_rl32(pb); - bink->file_size = get_le32(pb) + 8; - bink->total_frames = get_le32(pb); + bink->file_size = avio_rl32(pb) + 8; + vst->duration = avio_rl32(pb); - if (bink->total_frames > 1000000) { + if (vst->duration > 1000000) { av_log(s, AV_LOG_ERROR, "invalid header: more than 1000000 frames\n"); return AVERROR(EIO); } - if (get_le32(pb) > bink->file_size) { + if (avio_rl32(pb) > bink->file_size) { av_log(s, AV_LOG_ERROR, "invalid header: largest frame size greater than file size\n"); return AVERROR(EIO); } - url_fskip(pb, 4); + avio_skip(pb, 4); - vst->codec->width = get_le32(pb); - vst->codec->height = get_le32(pb); + vst->codec->width = avio_rl32(pb); + vst->codec->height = avio_rl32(pb); - fps_num = get_le32(pb); - fps_den = get_le32(pb); + fps_num = avio_rl32(pb); + fps_den = avio_rl32(pb); if (fps_num == 0 || fps_den == 0) { av_log(s, AV_LOG_ERROR, "invalid header: invalid fps (%d/%d)\n", fps_num, fps_den); return AVERROR(EIO); } av_set_pts_info(vst, 64, fps_den, fps_num); - url_fskip(pb, 4); - - vst->codec->codec_type = CODEC_TYPE_VIDEO; + vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; vst->codec->codec_id = CODEC_ID_BINKVIDEO; - bink->num_audio_tracks = get_le32(pb); + vst->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); + vst->codec->extradata_size = 4; + avio_read(pb, vst->codec->extradata, 4); + + bink->num_audio_tracks = avio_rl32(pb); if (bink->num_audio_tracks > BINK_MAX_AUDIO_TRACKS) { av_log(s, AV_LOG_ERROR, @@ -126,46 +127,54 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap) } if (bink->num_audio_tracks) { - url_fskip(pb, 4 * bink->num_audio_tracks); + avio_skip(pb, 4 * bink->num_audio_tracks); for (i = 0; i < bink->num_audio_tracks; i++) { ast = av_new_stream(s, 1); if (!ast) return AVERROR(ENOMEM); - ast->codec->codec_type = CODEC_TYPE_AUDIO; + ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_tag = 0; - ast->codec->sample_rate = get_le16(pb); + ast->codec->sample_rate = avio_rl16(pb); av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); - flags = get_le16(pb); + flags = avio_rl16(pb); ast->codec->codec_id = flags & BINK_AUD_USEDCT ? CODEC_ID_BINKAUDIO_DCT : CODEC_ID_BINKAUDIO_RDFT; ast->codec->channels = flags & BINK_AUD_STEREO ? 2 : 1; + ast->codec->extradata = av_mallocz(4 + FF_INPUT_BUFFER_PADDING_SIZE); + if (!ast->codec->extradata) + return AVERROR(ENOMEM); + ast->codec->extradata_size = 4; + AV_WL32(ast->codec->extradata, vst->codec->codec_tag); } - url_fskip(pb, 4 * bink->num_audio_tracks); + for (i = 0; i < bink->num_audio_tracks; i++) + s->streams[i + 1]->id = avio_rl32(pb); } /* frame index table */ - pos = get_le32(pb) & ~1; - for (i = 0; i < bink->total_frames; i++) { - prev_pos = pos; - if (i == bink->total_frames - 1) { - pos = bink->file_size; + next_pos = avio_rl32(pb); + for (i = 0; i < vst->duration; i++) { + pos = next_pos; + if (i == vst->duration - 1) { + next_pos = bink->file_size; keyframe = 0; } else { - pos = get_le32(pb); + next_pos = avio_rl32(pb); keyframe = pos & 1; - pos &= ~1; } - if (pos <= prev_pos) { + pos &= ~1; + next_pos &= ~1; + + if (next_pos <= pos) { av_log(s, AV_LOG_ERROR, "invalid frame index table\n"); return AVERROR(EIO); } - av_add_index_entry(vst, pos, i, pos - prev_pos, 0, + av_add_index_entry(vst, pos, i, next_pos - pos, 0, keyframe ? AVINDEX_KEYFRAME : 0); } - url_fskip(pb, 4); + avio_skip(pb, 4); bink->current_track = -1; return 0; @@ -174,14 +183,14 @@ static int read_header(AVFormatContext *s, AVFormatParameters *ap) static int read_packet(AVFormatContext *s, AVPacket *pkt) { BinkDemuxContext *bink = s->priv_data; - ByteIOContext *pb = s->pb; + AVIOContext *pb = s->pb; int ret; if (bink->current_track < 0) { int index_entry; AVStream *st = s->streams[0]; // stream 0 is video stream with index - if (bink->video_pts >= bink->total_frames) + if (bink->video_pts >= st->duration) return AVERROR(EIO); index_entry = av_index_search_timestamp(st, bink->video_pts, @@ -197,8 +206,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) bink->current_track = 0; } - if (bink->current_track < bink->num_audio_tracks) { - uint32_t audio_size = get_le32(pb); + while (bink->current_track < bink->num_audio_tracks) { + uint32_t audio_size = avio_rl32(pb); if (audio_size > bink->remain_packet_size - 4) { av_log(s, AV_LOG_ERROR, "frame %"PRId64": audio size in header (%u) > size of packet left (%u)\n", @@ -207,29 +216,30 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) } bink->remain_packet_size -= 4 + audio_size; bink->current_track++; - if (audio_size > 0) { - /* Each audio packet reports the number of decompressed samples - (in bytes). We use this value to calcuate the audio PTS */ - int reported_size = get_le32(pb) / (2 * s->streams[bink->current_track]->codec->channels); - url_fseek(pb, -4, SEEK_CUR); - + if (audio_size >= 4) { /* get one audio packet per track */ - if ((ret = av_get_packet(pb, pkt, audio_size)) - != audio_size) + if ((ret = av_get_packet(pb, pkt, audio_size)) < 0) return ret; pkt->stream_index = bink->current_track; - pkt->pts = bink->audio_pts[bink->current_track - 1] += reported_size; + pkt->pts = bink->audio_pts[bink->current_track - 1]; + + /* Each audio packet reports the number of decompressed samples + (in bytes). We use this value to calcuate the audio PTS */ + if (pkt->size >= 4) + bink->audio_pts[bink->current_track -1] += + AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec->channels); return 0; + } else { + avio_skip(pb, audio_size); } } /* get video packet */ - if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) - != bink->remain_packet_size) + if ((ret = av_get_packet(pb, pkt, bink->remain_packet_size)) < 0) return ret; pkt->stream_index = 0; pkt->pts = bink->video_pts++; - pkt->flags |= PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; /* -1 instructs the next call to read_packet() to read the next frame */ bink->current_track = -1; @@ -237,11 +247,28 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) return 0; } -AVInputFormat bink_demuxer = { - "bink", - NULL_IF_CONFIG_SMALL("Bink"), - sizeof(BinkDemuxContext), - probe, - read_header, - read_packet, +static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + BinkDemuxContext *bink = s->priv_data; + AVStream *vst = s->streams[0]; + + if (!s->pb->seekable) + return -1; + + /* seek to the first frame */ + avio_seek(s->pb, vst->index_entries[0].pos, SEEK_SET); + bink->video_pts = 0; + memset(bink->audio_pts, 0, sizeof(bink->audio_pts)); + bink->current_track = -1; + return 0; +} + +AVInputFormat ff_bink_demuxer = { + .name = "bink", + .long_name = NULL_IF_CONFIG_SMALL("Bink"), + .priv_data_size = sizeof(BinkDemuxContext), + .read_probe = probe, + .read_header = read_header, + .read_packet = read_packet, + .read_seek = read_seek, };