1/* 2 * PMP demuxer. 3 * Copyright (c) 2011 Reimar D��ffinger 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg 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. 11 * 12 * FFmpeg 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. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavutil/intreadwrite.h" 23#include "avformat.h" 24#include "internal.h" 25 26typedef struct { 27 int cur_stream; 28 int num_streams; 29 int audio_packets; 30 int current_packet; 31 uint32_t *packet_sizes; 32 int packet_sizes_alloc; 33} PMPContext; 34 35static int pmp_probe(AVProbeData *p) { 36 if (AV_RN32(p->buf) == AV_RN32("pmpm") && 37 AV_RL32(p->buf + 4) == 1) 38 return AVPROBE_SCORE_MAX; 39 return 0; 40} 41 42static int pmp_header(AVFormatContext *s) 43{ 44 PMPContext *pmp = s->priv_data; 45 AVIOContext *pb = s->pb; 46 int tb_num, tb_den; 47 uint32_t index_cnt; 48 int audio_codec_id = AV_CODEC_ID_NONE; 49 int srate, channels; 50 unsigned i; 51 uint64_t pos; 52 int64_t fsize = avio_size(pb); 53 54 AVStream *vst = avformat_new_stream(s, NULL); 55 if (!vst) 56 return AVERROR(ENOMEM); 57 vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; 58 avio_skip(pb, 8); 59 switch (avio_rl32(pb)) { 60 case 0: 61 vst->codec->codec_id = AV_CODEC_ID_MPEG4; 62 break; 63 case 1: 64 vst->codec->codec_id = AV_CODEC_ID_H264; 65 break; 66 default: 67 av_log(s, AV_LOG_ERROR, "Unsupported video format\n"); 68 break; 69 } 70 index_cnt = avio_rl32(pb); 71 vst->codec->width = avio_rl32(pb); 72 vst->codec->height = avio_rl32(pb); 73 74 tb_num = avio_rl32(pb); 75 tb_den = avio_rl32(pb); 76 avpriv_set_pts_info(vst, 32, tb_num, tb_den); 77 vst->nb_frames = index_cnt; 78 vst->duration = index_cnt; 79 80 switch (avio_rl32(pb)) { 81 case 0: 82 audio_codec_id = AV_CODEC_ID_MP3; 83 break; 84 case 1: 85 av_log(s, AV_LOG_ERROR, "AAC not yet correctly supported\n"); 86 audio_codec_id = AV_CODEC_ID_AAC; 87 break; 88 default: 89 av_log(s, AV_LOG_ERROR, "Unsupported audio format\n"); 90 break; 91 } 92 pmp->num_streams = avio_rl16(pb) + 1; 93 avio_skip(pb, 10); 94 srate = avio_rl32(pb); 95 channels = avio_rl32(pb) + 1; 96 pos = avio_tell(pb) + 4LL*index_cnt; 97 for (i = 0; i < index_cnt; i++) { 98 uint32_t size = avio_rl32(pb); 99 int flags = size & 1 ? AVINDEX_KEYFRAME : 0; 100 if (url_feof(pb)) { 101 av_log(s, AV_LOG_FATAL, "Encountered EOF while reading index.\n"); 102 return AVERROR_INVALIDDATA; 103 } 104 size >>= 1; 105 if (size < 9 + 4*pmp->num_streams) { 106 av_log(s, AV_LOG_ERROR, "Packet too small\n"); 107 return AVERROR_INVALIDDATA; 108 } 109 av_add_index_entry(vst, pos, i, size, 0, flags); 110 pos += size; 111 if (fsize > 0 && i == 0 && pos > fsize) { 112 av_log(s, AV_LOG_ERROR, "File ends before first packet\n"); 113 return AVERROR_INVALIDDATA; 114 } 115 } 116 for (i = 1; i < pmp->num_streams; i++) { 117 AVStream *ast = avformat_new_stream(s, NULL); 118 if (!ast) 119 return AVERROR(ENOMEM); 120 ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; 121 ast->codec->codec_id = audio_codec_id; 122 ast->codec->channels = channels; 123 ast->codec->sample_rate = srate; 124 avpriv_set_pts_info(ast, 32, 1, srate); 125 } 126 return 0; 127} 128 129static int pmp_packet(AVFormatContext *s, AVPacket *pkt) 130{ 131 PMPContext *pmp = s->priv_data; 132 AVIOContext *pb = s->pb; 133 int ret = 0; 134 int i; 135 136 if (url_feof(pb)) 137 return AVERROR_EOF; 138 if (pmp->cur_stream == 0) { 139 int num_packets; 140 pmp->audio_packets = avio_r8(pb); 141 142 if (!pmp->audio_packets) { 143 av_log(s, AV_LOG_ERROR, "No audio packets.\n"); 144 return AVERROR_INVALIDDATA; 145 } 146 147 num_packets = (pmp->num_streams - 1) * pmp->audio_packets + 1; 148 avio_skip(pb, 8); 149 pmp->current_packet = 0; 150 av_fast_malloc(&pmp->packet_sizes, 151 &pmp->packet_sizes_alloc, 152 num_packets * sizeof(*pmp->packet_sizes)); 153 if (!pmp->packet_sizes_alloc) { 154 av_log(s, AV_LOG_ERROR, "Cannot (re)allocate packet buffer\n"); 155 return AVERROR(ENOMEM); 156 } 157 for (i = 0; i < num_packets; i++) 158 pmp->packet_sizes[i] = avio_rl32(pb); 159 } 160 ret = av_get_packet(pb, pkt, pmp->packet_sizes[pmp->current_packet]); 161 if (ret >= 0) { 162 ret = 0; 163 pkt->stream_index = pmp->cur_stream; 164 } 165 if (pmp->current_packet % pmp->audio_packets == 0) 166 pmp->cur_stream = (pmp->cur_stream + 1) % pmp->num_streams; 167 pmp->current_packet++; 168 return ret; 169} 170 171static int pmp_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags) 172{ 173 PMPContext *pmp = s->priv_data; 174 pmp->cur_stream = 0; 175 // fall back on default seek now 176 return -1; 177} 178 179static int pmp_close(AVFormatContext *s) 180{ 181 PMPContext *pmp = s->priv_data; 182 av_freep(&pmp->packet_sizes); 183 return 0; 184} 185 186AVInputFormat ff_pmp_demuxer = { 187 .name = "pmp", 188 .long_name = NULL_IF_CONFIG_SMALL("Playstation Portable PMP"), 189 .priv_data_size = sizeof(PMPContext), 190 .read_probe = pmp_probe, 191 .read_header = pmp_header, 192 .read_packet = pmp_packet, 193 .read_seek = pmp_seek, 194 .read_close = pmp_close, 195}; 196