From 9397d0a1e5e2b998de8a1de3f9847e67334b4176 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Fri, 24 Apr 2009 10:00:25 -0500 Subject: [PATCH 3/4] 8088flex TMV demuxer --- libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/tmv.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 0 deletions(-) create mode 100644 libavformat/tmv.c diff --git a/libavformat/Makefile b/libavformat/Makefile index 55717e6..b9e5eb7 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -210,6 +210,7 @@ OBJS-$(CONFIG_TG2_MUXER) += movenc.o riff.o isom.o avc.o OBJS-$(CONFIG_TGP_MUXER) += movenc.o riff.o isom.o avc.o OBJS-$(CONFIG_THP_DEMUXER) += thp.o OBJS-$(CONFIG_TIERTEXSEQ_DEMUXER) += tiertexseq.o +OBJS-$(CONFIG_TMV_DEMUXER) += tmv.o OBJS-$(CONFIG_TRUEHD_DEMUXER) += raw.o id3v2.o OBJS-$(CONFIG_TRUEHD_MUXER) += raw.o OBJS-$(CONFIG_TTA_DEMUXER) += tta.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index e193af7..626b66c 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -182,6 +182,7 @@ void av_register_all(void) REGISTER_MUXER (TGP, tgp); REGISTER_DEMUXER (THP, thp); REGISTER_DEMUXER (TIERTEXSEQ, tiertexseq); + REGISTER_DEMUXER (TMV, tmv); REGISTER_MUXDEMUX (TRUEHD, truehd); REGISTER_DEMUXER (TTA, tta); REGISTER_DEMUXER (TXD, txd); diff --git a/libavformat/tmv.c b/libavformat/tmv.c new file mode 100644 index 0000000..c21042a --- /dev/null +++ b/libavformat/tmv.c @@ -0,0 +1,151 @@ +/* + * 8088flex TMV file demuxer + * Copyright (c) 2009 Daniel Verkamp + * + * This file is part of FFmpeg. + * + * FFmpeg 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, + * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * 8088flex TMV file demuxer + * @file libavformat/tmv.c + * @author Daniel Verkamp + * @sa http://www.oldskool.org/pc/8088_Corruption + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" + +enum { + TMV_PADDING = 0x01, + TMV_STEREO = 0x02, +}; + +#define TMV_TAG MKTAG('T', 'M', 'A', 'V') + +typedef struct TMVContext { + unsigned audio_chunk_size; + unsigned comp_method; + unsigned char_cols; + unsigned char_rows; + unsigned features; + + unsigned padding; + + unsigned stream_index; +} TMVContext; + +static int tmv_probe(AVProbeData *p) +{ + if (AV_RL32(p->buf) == TMV_TAG) + return AVPROBE_SCORE_MAX; + return 0; +} + +static int tmv_read_header(AVFormatContext *s, AVFormatParameters *ap) +{ + TMVContext *tmv = s->priv_data; + ByteIOContext *pb = s->pb; + AVStream *vst, *ast; + AVRational fps; + + if (get_le32(pb) != TMV_TAG) + return -1; + + if (!(vst = av_new_stream(s, 0))) + return AVERROR(ENOMEM); + + if (!(ast = av_new_stream(s, 0))) + return AVERROR(ENOMEM); + + ast->codec->sample_rate = get_le16(pb); + tmv->audio_chunk_size = get_le16(pb); + tmv->comp_method = get_byte(pb); + if (tmv->comp_method) { + av_log(s, AV_LOG_ERROR, "unsupported compression method %d\n", + tmv->comp_method); + return -1; + } + + tmv->char_cols = get_byte(pb); + tmv->char_rows = get_byte(pb); + + tmv->features = get_byte(pb); + if (tmv->features & ~(TMV_PADDING | TMV_STEREO)) { + av_log(s, AV_LOG_ERROR, "unsupported features 0x%02x\n", + tmv->features & ~(TMV_PADDING | TMV_STEREO)); + return -1; + } + + ast->codec->codec_type = CODEC_TYPE_AUDIO; + ast->codec->codec_id = CODEC_ID_PCM_U8; + ast->codec->sample_fmt = SAMPLE_FMT_U8; + ast->codec->channels = tmv->features & TMV_STEREO ? 2 : 1; + ast->codec->bits_per_coded_sample = 8; + ast->codec->bit_rate = ast->codec->sample_rate * + ast->codec->bits_per_coded_sample; + av_set_pts_info(ast, 32, 1, ast->codec->sample_rate); + + fps.num = ast->codec->sample_rate * ast->codec->channels; + fps.den = tmv->audio_chunk_size; + av_reduce(&fps.num, &fps.den, fps.num, fps.den, 0xFFFFFFFFLL); + + vst->codec->codec_type = CODEC_TYPE_VIDEO; + vst->codec->codec_id = CODEC_ID_TMV; + vst->codec->pix_fmt = PIX_FMT_PAL8; + vst->codec->width = tmv->char_cols * 8; + vst->codec->height = tmv->char_rows * 8; + av_set_pts_info(vst, 32, fps.den, fps.num); + + if (tmv->features & TMV_PADDING) + tmv->padding = ((2000 + tmv->audio_chunk_size + 511) & ~511) - + (2000 + tmv->audio_chunk_size); + + vst->codec->bit_rate = ((2000 + tmv->padding) * fps.num * 8) / fps.den; + + return 0; +} + +static int tmv_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + TMVContext *tmv = s->priv_data; + ByteIOContext *pb = s->pb; + int ret, pkt_size = tmv->stream_index ? tmv->audio_chunk_size : 2000; + + if (url_feof(pb)) + return AVERROR_EOF; + + ret = av_get_packet(pb, pkt, pkt_size); + + if (tmv->features & TMV_PADDING && tmv->stream_index) + url_fskip(pb, tmv->padding); + + pkt->stream_index = tmv->stream_index; + tmv->stream_index ^= 1; + pkt->flags |= PKT_FLAG_KEY; + + return ret; +} + +AVInputFormat tmv_demuxer = { + "tmv", + NULL_IF_CONFIG_SMALL("8088flex TMV"), + sizeof(TMVContext), + tmv_probe, + tmv_read_header, + tmv_read_packet, + .flags = AVFMT_GENERIC_INDEX, +}; -- 1.6.2.3