X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Frmdec.c;h=5110b0369c223e0e9439d1430c61c4e40a5aac18;hb=5f2c8315b3c1b28da0386fddb118ad6a0ed77a0c;hp=c85208b3fb25c9a79c3c9bf56631e8c9efafaba0;hpb=b8560637d93b632bd6b318baea4dc68b79e2ef85;p=ffmpeg diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index c85208b3fb2..5110b0369c2 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -19,15 +19,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" #include "internal.h" -#include "riff.h" +#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 @@ -50,7 +54,7 @@ struct RMStream { int32_t deint_id; ///< deinterleaver used in audio stream }; -typedef struct { +typedef struct RMDemuxContext { int nb_packets; int old_format; int current_stream; @@ -59,21 +63,6 @@ typedef struct { int audio_pkt_cnt; ///< Output packet counter } RMDemuxContext; -static const unsigned char sipr_swaps[38][2] = { - { 0, 63 }, { 1, 22 }, { 2, 44 }, { 3, 90 }, - { 5, 81 }, { 7, 31 }, { 8, 86 }, { 9, 58 }, - { 10, 36 }, { 12, 68 }, { 13, 39 }, { 14, 73 }, - { 15, 53 }, { 16, 69 }, { 17, 57 }, { 19, 88 }, - { 20, 34 }, { 21, 71 }, { 24, 46 }, { 25, 94 }, - { 26, 54 }, { 28, 75 }, { 29, 50 }, { 32, 70 }, - { 33, 92 }, { 35, 74 }, { 38, 85 }, { 40, 56 }, - { 42, 87 }, { 43, 65 }, { 45, 59 }, { 48, 79 }, - { 49, 93 }, { 51, 89 }, { 55, 95 }, { 61, 76 }, - { 67, 83 }, { 77, 80 } -}; - -const unsigned char ff_sipr_subpk_size[4] = { 29, 19, 37, 20 }; - static inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len) { int i; @@ -97,23 +86,22 @@ 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); + avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) 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; ipb) : 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); } } @@ -121,13 +109,15 @@ static void rm_read_metadata(AVFormatContext *s, int wide) RMStream *ff_rm_alloc_rmstream (void) { RMStream *rms = av_mallocz(sizeof(RMStream)); + if (!rms) + return NULL; rms->curpic_num = -1; return rms; } void ff_rm_free_rmstream (RMStream *rms) { - av_free_packet(&rms->pkt); + av_packet_unref(&rms->pkt); } static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, @@ -143,7 +133,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, int header_size = avio_rb16(pb); int64_t startpos = avio_tell(pb); avio_skip(pb, 14); - 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); @@ -154,8 +144,9 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, avio_skip(pb, header_size + startpos - avio_tell(pb)); st->codec->sample_rate = 8000; st->codec->channels = 1; + st->codec->channel_layout = AV_CH_LAYOUT_MONO; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = CODEC_ID_RA_144; + st->codec->codec_id = AV_CODEC_ID_RA_144; ast->deint_id = DEINT_ID_INT0; } else { int flavor, sub_packet_h, coded_framesize, sub_packet_size; @@ -196,28 +187,29 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, st->codec->codec_tag); switch (st->codec->codec_id) { - case CODEC_ID_AC3: + case AV_CODEC_ID_AC3: st->need_parsing = AVSTREAM_PARSE_FULL; break; - case CODEC_ID_RA_288: + case AV_CODEC_ID_RA_288: st->codec->extradata_size= 0; ast->audio_framesize = st->codec->block_align; st->codec->block_align = coded_framesize; break; - case CODEC_ID_COOK: - case CODEC_ID_ATRAC3: - case CODEC_ID_SIPR: + case AV_CODEC_ID_COOK: + st->need_parsing = AVSTREAM_PARSE_HEADERS; + case AV_CODEC_ID_ATRAC3: + case AV_CODEC_ID_SIPR: avio_rb16(pb); avio_r8(pb); if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } ast->audio_framesize = st->codec->block_align; - if (st->codec->codec_id == CODEC_ID_SIPR) { + if (st->codec->codec_id == AV_CODEC_ID_SIPR) { if (flavor > 3) { av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n", flavor); @@ -234,12 +226,12 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0) return ret; break; - case CODEC_ID_AAC: + case AV_CODEC_ID_AAC: avio_rb16(pb); avio_r8(pb); if (version == 5) avio_r8(pb); codecdata_length = avio_rb32(pb); - if(codecdata_length + FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length){ av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); return -1; } @@ -249,8 +241,6 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, return ret; } break; - 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 || @@ -280,7 +270,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, case DEINT_ID_VBRF: break; default: - av_log(NULL,0,"Unknown interleaver %X\n", ast->deint_id); + av_log(NULL, 0 ,"Unknown interleaver %"PRIX32"\n", ast->deint_id); return AVERROR_INVALIDDATA; } @@ -288,15 +278,15 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, avio_r8(pb); avio_r8(pb); avio_r8(pb); - rm_read_metadata(s, 0); + rm_read_metadata(s, pb, 0); } } return 0; } -int -ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, - AVStream *st, RMStream *rst, int codec_data_size) +int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb, + AVStream *st, RMStream *rst, + unsigned int codec_data_size) { unsigned int v; int size; @@ -323,14 +313,14 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, int fps; if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) { fail1: - av_log(st->codec, AV_LOG_ERROR, "Unsupported video codec\n"); + av_log(s, AV_LOG_WARNING, "Unsupported stream type %08x\n", v); goto skip; } st->codec->codec_tag = avio_rl32(pb); st->codec->codec_id = ff_codec_get_id(ff_rm_codec_tags, st->codec->codec_tag); -// av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); - if (st->codec->codec_id == CODEC_ID_NONE) + av_log(s, AV_LOG_TRACE, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); + if (st->codec->codec_id == AV_CODEC_ID_NONE) goto fail1; st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); @@ -343,9 +333,13 @@ 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->r_frame_rate.den, &st->r_frame_rate.num, - 0x10000, fps, (1 << 30) - 1); - st->avg_frame_rate = st->r_frame_rate; + if (fps > 0) { + av_reduce(&st->avg_frame_rate.den, &st->avg_frame_rate.num, + 0x10000, fps, (1 << 30) - 1); + } else if (s->error_recognition & AV_EF_EXPLODE) { + av_log(s, AV_LOG_ERROR, "Invalid framerate\n"); + return AVERROR_INVALIDDATA; + } } skip: @@ -424,6 +418,8 @@ static int rm_read_header_old(AVFormatContext *s) if (!st) return -1; st->priv_data = ff_rm_alloc_rmstream(); + if (!st->priv_data) + return AVERROR(ENOMEM); return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1); } @@ -456,7 +452,7 @@ static int rm_read_header(AVFormatContext *s) tag = avio_rl32(pb); tag_size = avio_rb32(pb); avio_rb16(pb); - av_dlog(s, "tag=%c%c%c%c (%08x) size=%d\n", + av_log(s, AV_LOG_TRACE, "tag=%c%c%c%c (%08x) size=%d\n", (tag ) & 0xff, (tag >> 8) & 0xff, (tag >> 16) & 0xff, @@ -481,7 +477,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); @@ -501,6 +497,8 @@ static int rm_read_header(AVFormatContext *s) get_str8(pb, buf, sizeof(buf)); /* mimetype */ st->codec->codec_type = AVMEDIA_TYPE_DATA; st->priv_data = ff_rm_alloc_rmstream(); + if (!st->priv_data) + return AVERROR(ENOMEM); if (ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, avio_rb32(pb)) < 0) return -1; @@ -661,7 +659,7 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){ vst->slices = ((hdr & 0x3F) << 1) + 1; vst->videobufsize = len2 + 8*vst->slices + 1; - av_free_packet(&vst->pkt); //FIXME this should be output. + av_packet_unref(&vst->pkt); //FIXME this should be output. if(av_new_packet(&vst->pkt, vst->videobufsize) < 0) return AVERROR(ENOMEM); vst->videobufpos = 8*vst->slices + 1; @@ -688,6 +686,7 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, *pkt= vst->pkt; vst->pkt.data= NULL; vst->pkt.size= 0; + vst->pkt.buf = NULL; 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, vst->videobufpos - 1 - 8*vst->slices); @@ -707,7 +706,7 @@ rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt) uint8_t *ptr; int j; - if (st->codec->codec_id == CODEC_ID_AC3) { + if (st->codec->codec_id == AV_CODEC_ID_AC3) { ptr = pkt->data; for (j=0;jsize;j+=2) { FFSWAP(int, ptr[0], ptr[1]); @@ -716,32 +715,6 @@ rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt) } } -/** - * Perform 4-bit block reordering for SIPR data. - * @todo This can be optimized, e.g. use memcpy() if data blocks are aligned - */ -void ff_rm_reorder_sipr_data(uint8_t *buf, int sub_packet_h, int framesize) -{ - int n, bs = sub_packet_h * framesize * 2 / 96; // nibbles per subpacket - - for (n = 0; n < 38; n++) { - int j; - int i = bs * sipr_swaps[n][0]; - int o = bs * sipr_swaps[n][1]; - - /* swap 4bit-nibbles of block 'i' with 'o' */ - for (j = 0; j < bs; j++, i++, o++) { - int x = (buf[i >> 1] >> (4 * (i & 1))) & 0xF, - y = (buf[o >> 1] >> (4 * (o & 1))) & 0xF; - - buf[o >> 1] = (x << (4 * (o & 1))) | - (buf[o >> 1] & (0xF << (4 * !(o & 1)))); - buf[i >> 1] = (y << (4 * (i & 1))) | - (buf[i >> 1] & (0xF << (4 * !(i & 1)))); - } - } -} - int ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, AVStream *st, RMStream *ast, int len, AVPacket *pkt, @@ -814,7 +787,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, #if 0 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if(st->codec->codec_id == CODEC_ID_RV20){ + if(st->codec->codec_id == AV_CODEC_ID_RV20){ int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1); av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq); @@ -844,7 +817,9 @@ ff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb, ast->deint_id == DEINT_ID_VBRS) av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); else { - av_new_packet(pkt, st->codec->block_align); + int ret = av_new_packet(pkt, st->codec->block_align); + if (ret < 0) + return ret; memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt), st->codec->block_align); @@ -891,7 +866,7 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) st = s->streams[i]; } - if(len<0 || s->pb->eof_reached) + if (len <= 0 || s->pb->eof_reached) return AVERROR(EIO); res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt, @@ -904,7 +879,7 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) || st->discard >= AVDISCARD_ALL){ - av_free_packet(pkt); + av_packet_unref(pkt); } else break; } @@ -966,7 +941,8 @@ static int64_t rm_read_dts(AVFormatContext *s, int stream_index, } if((flags&2) && (seq&0x7F) == 1){ -// av_log(s, AV_LOG_DEBUG, "%d %d-%d %"PRId64" %d\n", flags, stream_index2, stream_index, dts, seq); + av_log(s, AV_LOG_TRACE, "%d %d-%d %"PRId64" %d\n", + flags, stream_index2, stream_index, dts, seq); av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME); if(stream_index2 == stream_index) break; @@ -980,7 +956,7 @@ static int64_t rm_read_dts(AVFormatContext *s, int stream_index, AVInputFormat ff_rm_demuxer = { .name = "rm", - .long_name = NULL_IF_CONFIG_SMALL("RealMedia format"), + .long_name = NULL_IF_CONFIG_SMALL("RealMedia"), .priv_data_size = sizeof(RMDemuxContext), .read_probe = rm_probe, .read_header = rm_read_header,