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"
25 typedef struct PMPContext
{
30 uint32_t *packet_sizes
;
31 int packet_sizes_alloc
;
34 static int pmp_probe(AVProbeData
*p
)
36 if (!memcmp(p
->buf
, "pmpm\1\0\0\0", 8))
37 return AVPROBE_SCORE_MAX
;
41 static int pmp_header(AVFormatContext
*s
, AVFormatParameters
*ap
)
43 PMPContext
*pmp
= s
->priv_data
;
44 AVIOContext
*pb
= s
->pb
;
47 int audio_codec_id
= CODEC_ID_NONE
;
51 AVStream
*vst
= avformat_new_stream(s
, NULL
);
53 return AVERROR(ENOMEM
);
54 vst
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
56 switch (avio_rl32(pb
)) {
58 vst
->codec
->codec_id
= CODEC_ID_MPEG4
;
61 vst
->codec
->codec_id
= CODEC_ID_H264
;
64 av_log(s
, AV_LOG_ERROR
, "Unsupported video format\n");
67 index_cnt
= avio_rl32(pb
);
68 vst
->codec
->width
= avio_rl32(pb
);
69 vst
->codec
->height
= avio_rl32(pb
);
71 tb_num
= avio_rl32(pb
);
72 tb_den
= avio_rl32(pb
);
73 av_set_pts_info(vst
, 32, tb_num
, tb_den
);
74 vst
->nb_frames
= index_cnt
;
75 vst
->duration
= index_cnt
;
77 switch (avio_rl32(pb
)) {
79 audio_codec_id
= CODEC_ID_MP3
;
82 av_log(s
, AV_LOG_WARNING
, "AAC is not yet correctly supported\n");
83 audio_codec_id
= CODEC_ID_AAC
;
86 av_log(s
, AV_LOG_ERROR
, "Unsupported audio format\n");
89 pmp
->num_streams
= avio_rl16(pb
) + 1;
91 srate
= avio_rl32(pb
);
92 channels
= avio_rl32(pb
) + 1;
93 for (i
= 1; i
< pmp
->num_streams
; i
++) {
94 AVStream
*ast
= avformat_new_stream(s
, NULL
);
96 return AVERROR(ENOMEM
);
97 ast
->codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
98 ast
->codec
->codec_id
= audio_codec_id
;
99 ast
->codec
->channels
= channels
;
100 ast
->codec
->sample_rate
= srate
;
101 av_set_pts_info(ast
, 32, 1, srate
);
103 pos
= avio_tell(pb
) + 4 * index_cnt
;
104 for (i
= 0; i
< index_cnt
; i
++) {
105 int size
= avio_rl32(pb
);
106 int flags
= size
& 1 ? AVINDEX_KEYFRAME
: 0;
108 av_add_index_entry(vst
, pos
, i
, size
, 0, flags
);
114 static int pmp_packet(AVFormatContext
*s
, AVPacket
*pkt
)
116 PMPContext
*pmp
= s
->priv_data
;
117 AVIOContext
*pb
= s
->pb
;
123 if (pmp
->cur_stream
== 0) {
125 pmp
->audio_packets
= avio_r8(pb
);
126 num_packets
= (pmp
->num_streams
- 1) * pmp
->audio_packets
+ 1;
128 pmp
->current_packet
= 0;
129 av_fast_malloc(&pmp
->packet_sizes
,
130 &pmp
->packet_sizes_alloc
,
131 num_packets
* sizeof(*pmp
->packet_sizes
));
132 if (!pmp
->packet_sizes_alloc
) {
133 av_log(s
, AV_LOG_ERROR
, "Cannot (re)allocate packet buffer\n");
134 return AVERROR(ENOMEM
);
136 for (i
= 0; i
< num_packets
; i
++)
137 pmp
->packet_sizes
[i
] = avio_rl32(pb
);
139 ret
= av_get_packet(pb
, pkt
, pmp
->packet_sizes
[pmp
->current_packet
]);
142 // FIXME: this is a hack that should be removed once
143 // compute_pkt_fields() can handle timestamps properly
144 if (pmp
->cur_stream
== 0)
145 pkt
->dts
= s
->streams
[0]->cur_dts
++;
146 pkt
->stream_index
= pmp
->cur_stream
;
148 pmp
->current_packet
++;
149 if (pmp
->current_packet
== 1 || pmp
->current_packet
> pmp
->audio_packets
)
150 pmp
->cur_stream
= (pmp
->cur_stream
+ 1) % pmp
->num_streams
;
155 static int pmp_seek(AVFormatContext
*s
, int stream_idx
, int64_t ts
, int flags
)
157 PMPContext
*pmp
= s
->priv_data
;
159 // fallback to default seek now
163 static int pmp_close(AVFormatContext
*s
)
165 PMPContext
*pmp
= s
->priv_data
;
166 av_freep(&pmp
->packet_sizes
);
170 AVInputFormat ff_pmp_demuxer
= {
172 .long_name
= NULL_IF_CONFIG_SMALL("Playstation Portable PMP format"),
173 .priv_data_size
= sizeof(PMPContext
),
174 .read_probe
= pmp_probe
,
175 .read_header
= pmp_header
,
176 .read_packet
= pmp_packet
,
177 .read_seek
= pmp_seek
,
178 .read_close
= pmp_close
,