2 * Discworld II BMV demuxer
3 * Copyright (c) 2011 Konstantin Shishkov.
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/channel_layout.h"
35 typedef struct BMVContext
{
42 static int bmv_read_header(AVFormatContext
*s
)
45 BMVContext
*c
= s
->priv_data
;
47 st
= avformat_new_stream(s
, 0);
49 return AVERROR(ENOMEM
);
50 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
51 st
->codec
->codec_id
= AV_CODEC_ID_BMV_VIDEO
;
52 st
->codec
->width
= 640;
53 st
->codec
->height
= 429;
54 st
->codec
->pix_fmt
= AV_PIX_FMT_PAL8
;
55 avpriv_set_pts_info(st
, 16, 1, 12);
56 ast
= avformat_new_stream(s
, 0);
58 return AVERROR(ENOMEM
);
59 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
60 ast
->codec
->codec_id
= AV_CODEC_ID_BMV_AUDIO
;
61 ast
->codec
->channels
= 2;
62 ast
->codec
->channel_layout
= AV_CH_LAYOUT_STEREO
;
63 ast
->codec
->sample_rate
= 22050;
64 avpriv_set_pts_info(ast
, 16, 1, 22050);
71 static int bmv_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
73 BMVContext
*c
= s
->priv_data
;
78 if (s
->pb
->eof_reached
)
80 type
= avio_r8(s
->pb
);
85 c
->size
= avio_rl24(s
->pb
);
87 return AVERROR_INVALIDDATA
;
88 tmp
= av_realloc(c
->packet
, c
->size
+ 1);
90 return AVERROR(ENOMEM
);
93 if (avio_read(s
->pb
, c
->packet
+ 1, c
->size
) != c
->size
)
95 if (type
& BMV_AUDIO
) {
96 int audio_size
= c
->packet
[1] * 65 + 1;
97 if (audio_size
>= c
->size
) {
98 av_log(s
, AV_LOG_ERROR
, "Reported audio size %d is bigger than packet size (%d)\n",
100 return AVERROR_INVALIDDATA
;
102 if (av_new_packet(pkt
, audio_size
) < 0)
103 return AVERROR(ENOMEM
);
104 memcpy(pkt
->data
, c
->packet
+ 1, pkt
->size
);
105 pkt
->stream_index
= 1;
106 pkt
->pts
= c
->audio_pos
;
107 pkt
->duration
= c
->packet
[1] * 32;
108 c
->audio_pos
+= pkt
->duration
;
114 if (av_new_packet(pkt
, c
->size
+ 1) < 0)
115 return AVERROR(ENOMEM
);
116 pkt
->stream_index
= 0;
118 memcpy(pkt
->data
, c
->packet
, pkt
->size
);
122 static int bmv_read_close(AVFormatContext
*s
)
124 BMVContext
*c
= s
->priv_data
;
126 av_freep(&c
->packet
);
131 AVInputFormat ff_bmv_demuxer
= {
133 .long_name
= NULL_IF_CONFIG_SMALL("Discworld II BMV"),
134 .priv_data_size
= sizeof(BMVContext
),
135 .read_header
= bmv_read_header
,
136 .read_packet
= bmv_read_packet
,
137 .read_close
= bmv_read_close
,