annotate ffmpeg/libavformat/pmpdec.c @ 13:844d341cf643 tip

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