3 * Copyright (c) 2011 Reimar Döffinger
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/intreadwrite.h"
26 typedef struct PMPContext
{
31 uint32_t *packet_sizes
;
32 int packet_sizes_alloc
;
35 static int pmp_probe(AVProbeData
*p
)
37 if (!memcmp(p
->buf
, "pmpm\1\0\0\0", 8))
38 return AVPROBE_SCORE_MAX
;
42 static int pmp_header(AVFormatContext
*s
)
44 PMPContext
*pmp
= s
->priv_data
;
45 AVIOContext
*pb
= s
->pb
;
48 int audio_codec_id
= AV_CODEC_ID_NONE
;
52 AVStream
*vst
= avformat_new_stream(s
, NULL
);
54 return AVERROR(ENOMEM
);
55 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
57 switch (avio_rl32(pb
)) {
59 vst
->codec
->codec_id
= AV_CODEC_ID_MPEG4
;
62 vst
->codec
->codec_id
= AV_CODEC_ID_H264
;
65 av_log(s
, AV_LOG_ERROR
, "Unsupported video format\n");
68 index_cnt
= avio_rl32(pb
);
69 vst
->codec
->width
= avio_rl32(pb
);
70 vst
->codec
->height
= avio_rl32(pb
);
72 tb_num
= avio_rl32(pb
);
73 tb_den
= avio_rl32(pb
);
74 avpriv_set_pts_info(vst
, 32, tb_num
, tb_den
);
75 vst
->nb_frames
= index_cnt
;
76 vst
->duration
= index_cnt
;
78 switch (avio_rl32(pb
)) {
80 audio_codec_id
= AV_CODEC_ID_MP3
;
83 av_log(s
, AV_LOG_WARNING
, "AAC is not yet correctly supported\n");
84 audio_codec_id
= AV_CODEC_ID_AAC
;
87 av_log(s
, AV_LOG_ERROR
, "Unsupported audio format\n");
90 pmp
->num_streams
= avio_rl16(pb
) + 1;
92 srate
= avio_rl32(pb
);
93 channels
= avio_rl32(pb
) + 1;
94 for (i
= 1; i
< pmp
->num_streams
; i
++) {
95 AVStream
*ast
= avformat_new_stream(s
, NULL
);
97 return AVERROR(ENOMEM
);
98 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
99 ast
->codec
->codec_id
= audio_codec_id
;
100 ast
->codec
->channels
= channels
;
101 ast
->codec
->sample_rate
= srate
;
102 avpriv_set_pts_info(ast
, 32, 1, srate
);
104 pos
= avio_tell(pb
) + 4 * index_cnt
;
105 for (i
= 0; i
< index_cnt
; i
++) {
106 int size
= avio_rl32(pb
);
107 int flags
= size
& 1 ? AVINDEX_KEYFRAME
: 0;
109 av_add_index_entry(vst
, pos
, i
, size
, 0, flags
);
115 static int pmp_packet(AVFormatContext
*s
, AVPacket
*pkt
)
117 PMPContext
*pmp
= s
->priv_data
;
118 AVIOContext
*pb
= s
->pb
;
124 if (pmp
->cur_stream
== 0) {
126 pmp
->audio_packets
= avio_r8(pb
);
127 num_packets
= (pmp
->num_streams
- 1) * pmp
->audio_packets
+ 1;
129 pmp
->current_packet
= 0;
130 av_fast_malloc(&pmp
->packet_sizes
,
131 &pmp
->packet_sizes_alloc
,
132 num_packets
* sizeof(*pmp
->packet_sizes
));
133 if (!pmp
->packet_sizes_alloc
) {
134 av_log(s
, AV_LOG_ERROR
, "Cannot (re)allocate packet buffer\n");
135 return AVERROR(ENOMEM
);
137 for (i
= 0; i
< num_packets
; i
++)
138 pmp
->packet_sizes
[i
] = avio_rl32(pb
);
140 ret
= av_get_packet(pb
, pkt
, pmp
->packet_sizes
[pmp
->current_packet
]);
143 // FIXME: this is a hack that should be removed once
144 // compute_pkt_fields() can handle timestamps properly
145 if (pmp
->cur_stream
== 0)
146 pkt
->dts
= s
->streams
[0]->cur_dts
++;
147 pkt
->stream_index
= pmp
->cur_stream
;
149 pmp
->current_packet
++;
150 if (pmp
->current_packet
== 1 || pmp
->current_packet
> pmp
->audio_packets
)
151 pmp
->cur_stream
= (pmp
->cur_stream
+ 1) % pmp
->num_streams
;
156 static int pmp_seek(AVFormatContext
*s
, int stream_idx
, int64_t ts
, int flags
)
158 PMPContext
*pmp
= s
->priv_data
;
160 // fallback to default seek now
164 static int pmp_close(AVFormatContext
*s
)
166 PMPContext
*pmp
= s
->priv_data
;
167 av_freep(&pmp
->packet_sizes
);
171 AVInputFormat ff_pmp_demuxer
= {
173 .long_name
= NULL_IF_CONFIG_SMALL("Playstation Portable PMP"),
174 .priv_data_size
= sizeof(PMPContext
),
175 .read_probe
= pmp_probe
,
176 .read_header
= pmp_header
,
177 .read_packet
= pmp_packet
,
178 .read_seek
= pmp_seek
,
179 .read_close
= pmp_close
,