LCOV - code coverage report
Current view: top level - libavformat - pmpdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 111 73.9 %
Date: 2017-12-18 13:19:42 Functions: 4 5 80.0 %

          Line data    Source code
       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             : 
      26             : typedef 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             : 
      35        6130 : static int pmp_probe(AVProbeData *p) {
      36        6131 :     if (AV_RN32(p->buf) == AV_RN32("pmpm") &&
      37           1 :         AV_RL32(p->buf + 4) == 1)
      38           1 :         return AVPROBE_SCORE_MAX;
      39        6129 :     return 0;
      40             : }
      41             : 
      42           1 : static int pmp_header(AVFormatContext *s)
      43             : {
      44           1 :     PMPContext *pmp = s->priv_data;
      45           1 :     AVIOContext *pb = s->pb;
      46             :     int tb_num, tb_den;
      47             :     uint32_t index_cnt;
      48           1 :     int audio_codec_id = AV_CODEC_ID_NONE;
      49             :     int srate, channels;
      50             :     unsigned i;
      51             :     uint64_t pos;
      52           1 :     int64_t fsize = avio_size(pb);
      53             : 
      54           1 :     AVStream *vst = avformat_new_stream(s, NULL);
      55           1 :     if (!vst)
      56           0 :         return AVERROR(ENOMEM);
      57           1 :     vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
      58           1 :     avio_skip(pb, 8);
      59           1 :     switch (avio_rl32(pb)) {
      60           1 :     case 0:
      61           1 :         vst->codecpar->codec_id = AV_CODEC_ID_MPEG4;
      62           1 :         break;
      63           0 :     case 1:
      64           0 :         vst->codecpar->codec_id = AV_CODEC_ID_H264;
      65           0 :         break;
      66           0 :     default:
      67           0 :         av_log(s, AV_LOG_ERROR, "Unsupported video format\n");
      68           0 :         break;
      69             :     }
      70           1 :     index_cnt          = avio_rl32(pb);
      71           1 :     vst->codecpar->width  = avio_rl32(pb);
      72           1 :     vst->codecpar->height = avio_rl32(pb);
      73             : 
      74           1 :     tb_num = avio_rl32(pb);
      75           1 :     tb_den = avio_rl32(pb);
      76           1 :     avpriv_set_pts_info(vst, 32, tb_num, tb_den);
      77           1 :     vst->nb_frames = index_cnt;
      78           1 :     vst->duration = index_cnt;
      79             : 
      80           1 :     switch (avio_rl32(pb)) {
      81           1 :     case 0:
      82           1 :         audio_codec_id = AV_CODEC_ID_MP3;
      83           1 :         break;
      84           0 :     case 1:
      85           0 :         av_log(s, AV_LOG_ERROR, "AAC not yet correctly supported\n");
      86           0 :         audio_codec_id = AV_CODEC_ID_AAC;
      87           0 :         break;
      88           0 :     default:
      89           0 :         av_log(s, AV_LOG_ERROR, "Unsupported audio format\n");
      90           0 :         break;
      91             :     }
      92           1 :     pmp->num_streams = avio_rl16(pb) + 1;
      93           1 :     avio_skip(pb, 10);
      94           1 :     srate = avio_rl32(pb);
      95           1 :     channels = avio_rl32(pb) + 1;
      96           1 :     pos = avio_tell(pb) + 4LL*index_cnt;
      97        1320 :     for (i = 0; i < index_cnt; i++) {
      98        1319 :         uint32_t size = avio_rl32(pb);
      99        1319 :         int flags = size & 1 ? AVINDEX_KEYFRAME : 0;
     100        1319 :         if (avio_feof(pb)) {
     101           0 :             av_log(s, AV_LOG_FATAL, "Encountered EOF while reading index.\n");
     102           0 :             return AVERROR_INVALIDDATA;
     103             :         }
     104        1319 :         size >>= 1;
     105        1319 :         if (size < 9 + 4*pmp->num_streams) {
     106           0 :             av_log(s, AV_LOG_ERROR, "Packet too small\n");
     107           0 :             return AVERROR_INVALIDDATA;
     108             :         }
     109        1319 :         av_add_index_entry(vst, pos, i, size, 0, flags);
     110        1319 :         pos += size;
     111        1319 :         if (fsize > 0 && i == 0 && pos > fsize) {
     112           0 :             av_log(s, AV_LOG_ERROR, "File ends before first packet\n");
     113           0 :             return AVERROR_INVALIDDATA;
     114             :         }
     115             :     }
     116           2 :     for (i = 1; i < pmp->num_streams; i++) {
     117           1 :         AVStream *ast = avformat_new_stream(s, NULL);
     118           1 :         if (!ast)
     119           0 :             return AVERROR(ENOMEM);
     120           1 :         ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
     121           1 :         ast->codecpar->codec_id    = audio_codec_id;
     122           1 :         ast->codecpar->channels    = channels;
     123           1 :         ast->codecpar->sample_rate = srate;
     124           1 :         avpriv_set_pts_info(ast, 32, 1, srate);
     125             :     }
     126           1 :     return 0;
     127             : }
     128             : 
     129         189 : static int pmp_packet(AVFormatContext *s, AVPacket *pkt)
     130             : {
     131         189 :     PMPContext *pmp = s->priv_data;
     132         189 :     AVIOContext *pb = s->pb;
     133         189 :     int ret = 0;
     134             :     int i;
     135             : 
     136         189 :     if (avio_feof(pb))
     137           1 :         return AVERROR_EOF;
     138         188 :     if (pmp->cur_stream == 0) {
     139             :         int num_packets;
     140          83 :         pmp->audio_packets = avio_r8(pb);
     141             : 
     142          83 :         if (!pmp->audio_packets) {
     143           0 :             av_log(s, AV_LOG_ERROR, "No audio packets.\n");
     144           0 :             return AVERROR_INVALIDDATA;
     145             :         }
     146             : 
     147          83 :         num_packets = (pmp->num_streams - 1) * pmp->audio_packets + 1;
     148          83 :         avio_skip(pb, 8);
     149          83 :         pmp->current_packet = 0;
     150         166 :         av_fast_malloc(&pmp->packet_sizes,
     151          83 :                        &pmp->packet_sizes_alloc,
     152             :                        num_packets * sizeof(*pmp->packet_sizes));
     153          83 :         if (!pmp->packet_sizes_alloc) {
     154           0 :             av_log(s, AV_LOG_ERROR, "Cannot (re)allocate packet buffer\n");
     155           0 :             return AVERROR(ENOMEM);
     156             :         }
     157         273 :         for (i = 0; i < num_packets; i++)
     158         190 :             pmp->packet_sizes[i] = avio_rl32(pb);
     159             :     }
     160         188 :     ret = av_get_packet(pb, pkt, pmp->packet_sizes[pmp->current_packet]);
     161         188 :     if (ret >= 0) {
     162         188 :         ret = 0;
     163         188 :         pkt->stream_index = pmp->cur_stream;
     164             :     }
     165         188 :     if (pmp->current_packet % pmp->audio_packets == 0)
     166         165 :         pmp->cur_stream = (pmp->cur_stream + 1) % pmp->num_streams;
     167         188 :     pmp->current_packet++;
     168         188 :     return ret;
     169             : }
     170             : 
     171           0 : static int pmp_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags)
     172             : {
     173           0 :     PMPContext *pmp = s->priv_data;
     174           0 :     pmp->cur_stream = 0;
     175             :     // fall back on default seek now
     176           0 :     return -1;
     177             : }
     178             : 
     179           1 : static int pmp_close(AVFormatContext *s)
     180             : {
     181           1 :     PMPContext *pmp = s->priv_data;
     182           1 :     av_freep(&pmp->packet_sizes);
     183           1 :     return 0;
     184             : }
     185             : 
     186             : AVInputFormat 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             : };

Generated by: LCOV version 1.13