summaryrefslogtreecommitdiff
path: root/ffmpeg/libavformat/rmdec.c
diff options
context:
space:
mode:
authorTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
committerTim Redfern <tim@eclectronics.org>2013-12-29 12:19:38 +0000
commitf7813a5324be39d13ab536c245d15dfc602a7849 (patch)
treefad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavformat/rmdec.c
parentb7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff)
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavformat/rmdec.c')
-rw-r--r--ffmpeg/libavformat/rmdec.c95
1 files changed, 62 insertions, 33 deletions
diff --git a/ffmpeg/libavformat/rmdec.c b/ffmpeg/libavformat/rmdec.c
index 478b35b..8feef54 100644
--- a/ffmpeg/libavformat/rmdec.c
+++ b/ffmpeg/libavformat/rmdec.c
@@ -22,6 +22,7 @@
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
+#include "libavutil/internal.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "avformat.h"
@@ -30,7 +31,7 @@
#include "rmsipr.h"
#include "rm.h"
-#define DEINT_ID_GENR MKTAG('g', 'e', 'n', 'r') ///< interleaving for Cooker/Atrac
+#define DEINT_ID_GENR MKTAG('g', 'e', 'n', 'r') ///< interleaving for Cooker/ATRAC
#define DEINT_ID_INT0 MKTAG('I', 'n', 't', '0') ///< no interleaving needed
#define DEINT_ID_INT4 MKTAG('I', 'n', 't', '4') ///< interleaving for 28.8
#define DEINT_ID_SIPR MKTAG('s', 'i', 'p', 'r') ///< interleaving for Sipro
@@ -85,23 +86,19 @@ static int rm_read_extradata(AVIOContext *pb, AVCodecContext *avctx, unsigned si
{
if (size >= 1<<24)
return -1;
- avctx->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (!avctx->extradata)
+ if (ff_get_extradata(avctx, pb, size) < 0)
return AVERROR(ENOMEM);
- avctx->extradata_size = avio_read(pb, avctx->extradata, size);
- memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- if (avctx->extradata_size != size)
- return AVERROR(EIO);
return 0;
}
-static void rm_read_metadata(AVFormatContext *s, int wide)
+static void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide)
{
char buf[1024];
int i;
+
for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
- int len = wide ? avio_rb16(s->pb) : avio_r8(s->pb);
- get_strl(s->pb, buf, sizeof(buf), len);
+ int len = wide ? avio_rb16(pb) : avio_r8(pb);
+ get_strl(pb, buf, sizeof(buf), len);
av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0);
}
}
@@ -134,7 +131,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
avio_skip(pb, 8);
bytes_per_minute = avio_rb16(pb);
avio_skip(pb, 4);
- rm_read_metadata(s, 0);
+ rm_read_metadata(s, pb, 0);
if ((startpos + header_size) >= avio_tell(pb) + 2) {
// fourcc (should always be "lpcJ")
avio_r8(pb);
@@ -185,6 +182,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
avio_read(pb, buf, 4);
buf[4] = 0;
} else {
+ AV_WL32(buf, 0);
get_str8(pb, buf, sizeof(buf)); /* desc */
ast->deint_id = AV_RL32(buf);
get_str8(pb, buf, sizeof(buf)); /* desc */
@@ -257,22 +255,16 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
default:
av_strlcpy(st->codec->codec_name, buf, sizeof(st->codec->codec_name));
}
- if (ast->deint_id == DEINT_ID_INT4 ||
- ast->deint_id == DEINT_ID_GENR ||
- ast->deint_id == DEINT_ID_SIPR) {
- if (st->codec->block_align <= 0 ||
- ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX ||
- ast->audio_framesize * sub_packet_h < st->codec->block_align)
- return AVERROR_INVALIDDATA;
- if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
- return AVERROR(ENOMEM);
- }
switch (ast->deint_id) {
case DEINT_ID_INT4:
if (ast->coded_framesize > ast->audio_framesize ||
sub_packet_h <= 1 ||
ast->coded_framesize * sub_packet_h > (2 + (sub_packet_h & 1)) * ast->audio_framesize)
return AVERROR_INVALIDDATA;
+ if (ast->coded_framesize * sub_packet_h != 2*ast->audio_framesize) {
+ avpriv_request_sample(s, "mismatching interleaver parameters");
+ return AVERROR_INVALIDDATA;
+ }
break;
case DEINT_ID_GENR:
if (ast->sub_packet_size <= 0 ||
@@ -288,12 +280,22 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
av_log(s, AV_LOG_ERROR, "Unknown interleaver %X\n", ast->deint_id);
return AVERROR_INVALIDDATA;
}
+ if (ast->deint_id == DEINT_ID_INT4 ||
+ ast->deint_id == DEINT_ID_GENR ||
+ ast->deint_id == DEINT_ID_SIPR) {
+ if (st->codec->block_align <= 0 ||
+ ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX ||
+ ast->audio_framesize * sub_packet_h < st->codec->block_align)
+ return AVERROR_INVALIDDATA;
+ if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
+ return AVERROR(ENOMEM);
+ }
if (read_all) {
avio_r8(pb);
avio_r8(pb);
avio_r8(pb);
- rm_read_metadata(s, 0);
+ rm_read_metadata(s, pb, 0);
}
}
return 0;
@@ -375,11 +377,16 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb,
if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
return ret;
- av_reduce(&st->avg_frame_rate.den, &st->avg_frame_rate.num,
- 0x10000, fps, (1 << 30) - 1);
+ if (fps > 0) {
+ av_reduce(&st->avg_frame_rate.den, &st->avg_frame_rate.num,
+ 0x10000, fps, (1 << 30) - 1);
#if FF_API_R_FRAME_RATE
- st->r_frame_rate = st->avg_frame_rate;
+ st->r_frame_rate = st->avg_frame_rate;
#endif
+ } else if (s->error_recognition & AV_EF_EXPLODE) {
+ av_log(s, AV_LOG_ERROR, "Invalid framerate\n");
+ return AVERROR_INVALIDDATA;
+ }
}
skip:
@@ -516,7 +523,7 @@ static int rm_read_header(AVFormatContext *s)
flags = avio_rb16(pb); /* flags */
break;
case MKTAG('C', 'O', 'N', 'T'):
- rm_read_metadata(s, 1);
+ rm_read_metadata(s, pb, 1);
break;
case MKTAG('M', 'D', 'P', 'R'):
st = avformat_new_stream(s, NULL);
@@ -662,6 +669,7 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
int hdr;
int seq = 0, pic_num = 0, len2 = 0, pos = 0; //init to silcense compiler warning
int type;
+ int ret;
hdr = avio_r8(pb); len--;
type = hdr >> 6;
@@ -674,23 +682,31 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
pos = get_num(pb, &len);
pic_num = avio_r8(pb); len--;
}
- if(len<0)
+ if(len<0) {
+ av_log(s, AV_LOG_ERROR, "Insufficient data\n");
return -1;
+ }
rm->remaining_len = len;
if(type&1){ // frame, not slice
if(type == 3){ // frame as a part of packet
len= len2;
*timestamp = pos;
}
- if(rm->remaining_len < len)
+ if(rm->remaining_len < len) {
+ av_log(s, AV_LOG_ERROR, "Insufficient remaining len\n");
return -1;
+ }
rm->remaining_len -= len;
if(av_new_packet(pkt, len + 9) < 0)
return AVERROR(EIO);
pkt->data[0] = 0;
AV_WL32(pkt->data + 1, 1);
AV_WL32(pkt->data + 5, 0);
- avio_read(pb, pkt->data + 9, len);
+ if ((ret = avio_read(pb, pkt->data + 9, len)) != len) {
+ av_free_packet(pkt);
+ av_log(s, AV_LOG_ERROR, "Failed to read %d bytes\n", len);
+ return ret < 0 ? ret : AVERROR(EIO);
+ }
return 0;
}
//now we have to deal with single slice
@@ -706,6 +722,7 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
av_free_packet(&vst->pkt); //FIXME this should be output.
if(av_new_packet(&vst->pkt, vst->videobufsize) < 0)
return AVERROR(ENOMEM);
+ memset(vst->pkt.data, 0, vst->pkt.size);
vst->videobufpos = 8*vst->slices + 1;
vst->cur_slice = 0;
vst->curpic_num = pic_num;
@@ -714,12 +731,18 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
if(type == 2)
len = FFMIN(len, pos);
- if(++vst->cur_slice > vst->slices)
+ if(++vst->cur_slice > vst->slices) {
+ av_log(s, AV_LOG_ERROR, "cur slice %d, too large\n", vst->cur_slice);
return 1;
+ }
+ if(!vst->pkt.data)
+ return AVERROR(ENOMEM);
AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1);
AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1);
- if(vst->videobufpos + len > vst->videobufsize)
+ if(vst->videobufpos + len > vst->videobufsize) {
+ av_log(s, AV_LOG_ERROR, "outside videobufsize\n");
return 1;
+ }
if (avio_read(pb, vst->pkt.data + vst->videobufpos, len) != len)
return AVERROR(EIO);
vst->videobufpos += len;
@@ -732,7 +755,9 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
vst->pkt.size= 0;
vst->pkt.buf = NULL;
#if FF_API_DESTRUCT_PACKET
+FF_DISABLE_DEPRECATION_WARNINGS
vst->pkt.destruct = NULL;
+FF_ENABLE_DEPRECATION_WARNINGS
#endif
if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin
memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
@@ -768,11 +793,13 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
int *seq, int flags, int64_t timestamp)
{
RMDemuxContext *rm = s->priv_data;
+ int ret;
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
rm->current_stream= st->id;
- if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, &timestamp))
- return -1; //got partial frame
+ ret = rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, &timestamp);
+ if(ret)
+ return ret < 0 ? ret : -1; //got partial frame or error
} else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
if ((ast->deint_id == DEINT_ID_GENR) ||
(ast->deint_id == DEINT_ID_INT4) ||
@@ -919,6 +946,8 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt)
res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt,
&seq, flags, timestamp);
+ if (res < -1)
+ return res;
if((flags&2) && (seq&0x7F) == 1)
av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME);
if (res)