diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-09-21 21:25:43 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-09-21 21:25:43 +0200 |
commit | 3e1a7ae44a97f20bbc9da0eba000663ef74e1890 (patch) | |
tree | 75bfd6ad30f1b24aa7d29c3a3081875c14b5dab5 | |
parent | 358d837dad4e2fbe010553990383d0ca4d5937cf (diff) | |
parent | 05fc9e40a4e4f808d457512420b887f458d216bc (diff) | |
download | ffmpeg-3e1a7ae44a97f20bbc9da0eba000663ef74e1890.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
swfdec: Add support for sample_rate_code 0 (5512 Hz)
dct-test: factor out some common code and do whas was likely intended
doc: library versions need to be bumped in version.h
Revert "ffmpeg: get rid of useless AVInputStream.nb_streams."
Remove some forgotten AVCodecContext.palctrl usage.
lavc/utils: move avcodec_init() higher in the file.
lavc: replace some deprecated FF_*_TYPE with AV_PICTURE_TYPE_*
ac3dec: actually use drc_scale private option
lavc: undeprecate AVPALETTE_SIZE and AVPALETTE_COUNT macros
alsa: add missing header
msmpeg4: remove leftover unused debug variable declaration
Fix assert() calls that need updates after FF_COMMON_FRAME macro elimination.
Fix av_dlog invocations with wrong or missing logging context.
vf_yadif: add support to yuva420p
vf_yadif: correct documentation on the parity parameter
vf_yadif: copy buffer properties like aspect for second frame as well
oma: support for encrypted files
id3v2: add support for non-text and GEOB type tag frames
des: add possibility to calculate DES-CBC-MAC with small buffer
Conflicts:
ffmpeg.c
libavcodec/dct-test.c
libavformat/mpegts.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | doc/developer.texi | 2 | ||||
-rw-r--r-- | libavcodec/ac3dec.c | 7 | ||||
-rw-r--r-- | libavcodec/avcodec.h | 4 | ||||
-rw-r--r-- | libavcodec/dct-test.c | 127 | ||||
-rw-r--r-- | libavcodec/h261dec.c | 4 | ||||
-rw-r--r-- | libavcodec/h264.c | 2 | ||||
-rw-r--r-- | libavcodec/h264_direct.c | 4 | ||||
-rw-r--r-- | libavcodec/mpeg12.c | 2 | ||||
-rw-r--r-- | libavcodec/mpegvideo.c | 8 | ||||
-rw-r--r-- | libavcodec/mpegvideo_enc.c | 10 | ||||
-rw-r--r-- | libavcodec/msmpeg4.c | 4 | ||||
-rw-r--r-- | libavcodec/options.c | 4 | ||||
-rw-r--r-- | libavcodec/utils.c | 28 | ||||
-rw-r--r-- | libavdevice/alsa-audio-common.c | 1 | ||||
-rw-r--r-- | libavformat/id3v2.c | 270 | ||||
-rw-r--r-- | libavformat/id3v2.h | 38 | ||||
-rw-r--r-- | libavformat/mov.c | 2 | ||||
-rw-r--r-- | libavformat/mpegts.c | 2 | ||||
-rw-r--r-- | libavformat/oma.c | 269 | ||||
-rw-r--r-- | libavformat/swfdec.c | 5 | ||||
-rw-r--r-- | libavutil/des.c | 13 | ||||
-rw-r--r-- | libavutil/des.h | 11 |
22 files changed, 644 insertions, 173 deletions
diff --git a/doc/developer.texi b/doc/developer.texi index eab415c39a..29291d0c71 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -310,7 +310,7 @@ send a reminder by email. Your patch should eventually be dealt with. AVInputFormat/AVOutputFormat struct? @item Did you bump the minor version number (and reset the micro version - number) in @file{avcodec.h} or @file{avformat.h}? + number) in @file{libavcodec/version.h} or @file{libavformat/version.h}? @item Did you register it in @file{allcodecs.c} or @file{allformats.c}? @item diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 503db5e201..9d1611f226 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -176,6 +176,11 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) AC3DecodeContext *s = avctx->priv_data; s->avctx = avctx; +#if FF_API_DRC_SCALE + if (avctx->drc_scale) + s->drc_scale = avctx->drc_scale; +#endif + ff_ac3_common_init(); ac3_tables_init(); ff_mdct_init(&s->imdct_256, 8, 1, 1.0); @@ -788,7 +793,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk) do { if(get_bits1(gbc)) { s->dynamic_range[i] = ((dynamic_range_tab[get_bits(gbc, 8)]-1.0) * - s->avctx->drc_scale)+1.0; + s->drc_scale)+1.0; } else if(blk == 0) { s->dynamic_range[i] = 1.0f; } diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f4f895537c..8e89e997d0 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3149,6 +3149,8 @@ typedef struct AVPicture { int linesize[4]; ///< number of bytes per line } AVPicture; +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 #if FF_API_PALETTE_CONTROL /** * AVPaletteControl @@ -3158,8 +3160,6 @@ typedef struct AVPicture { * @deprecated Use AVPacket to send palette changes instead. * This is totally broken. */ -#define AVPALETTE_SIZE 1024 -#define AVPALETTE_COUNT 256 typedef struct AVPaletteControl { /* Demuxer sets this to 1 to indicate the palette has changed; diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 9e1e99672b..2222cd5144 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -199,6 +199,55 @@ static inline void mmx_emms(void) #endif } +static void init_block(DCTELEM block[64], int test, int is_idct, AVLFG *prng, int vals) +{ + int i, j; + + memset(block, 0, 64 * sizeof(*block)); + + switch (test) { + case 0: + for (i = 0; i < 64; i++) + block[i] = (av_lfg_get(prng) % (2*vals)) -vals; + if (is_idct) { + ff_ref_fdct(block); + for (i = 0; i < 64; i++) + block[i] >>= 3; + } + break; + case 1: + j = av_lfg_get(prng) % 10 + 1; + for (i = 0; i < j; i++) + block[av_lfg_get(prng) % 64] = av_lfg_get(prng) % (2*vals) -vals; + break; + case 2: + block[ 0] = av_lfg_get(prng) % (16*vals) - (8*vals); + block[63] = (block[0] & 1) ^ 1; + break; + } +} + +static void permute(DCTELEM dst[64], const DCTELEM src[64], int perm) +{ + int i; + + if (perm == MMX_PERM) { + for (i = 0; i < 64; i++) + dst[idct_mmx_perm[i]] = src[i]; + } else if (perm == MMX_SIMPLE_PERM) { + for (i = 0; i < 64; i++) + dst[idct_simple_mmx_perm[i]] = src[i]; + } else if (perm == SSE2_PERM) { + for (i = 0; i < 64; i++) + dst[(i & 0x38) | idct_sse2_row_perm[i & 7]] = src[i]; + } else if (perm == PARTTRANS_PERM) { + for (i = 0; i < 64; i++) + dst[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = src[i]; + } else { + for (i = 0; i < 64; i++) + dst[i] = src[i]; + } +} static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits) { @@ -221,46 +270,8 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed, c for (i = 0; i < 64; i++) sysErr[i] = 0; for (it = 0; it < NB_ITS; it++) { - for (i = 0; i < 64; i++) - block1[i] = 0; - switch (test) { - case 0: - for (i = 0; i < 64; i++) - block1[i] = (av_lfg_get(&prng) % (2*vals)) -vals; - if (is_idct) { - ff_ref_fdct(block1); - for (i = 0; i < 64; i++) - block1[i] >>= 3; - } - break; - case 1: { - int num = av_lfg_get(&prng) % 10 + 1; - for (i = 0; i < num; i++) - block1[av_lfg_get(&prng) % 64] = av_lfg_get(&prng) % (2*vals) -vals; - } - break; - case 2: - block1[0] = av_lfg_get(&prng) % (16*vals) - (8*vals); - block1[63] = (block1[0] & 1) ^ 1; - break; - } - - if (dct->format == MMX_PERM) { - for (i = 0; i < 64; i++) - block[idct_mmx_perm[i]] = block1[i]; - } else if (dct->format == MMX_SIMPLE_PERM) { - for (i = 0; i < 64; i++) - block[idct_simple_mmx_perm[i]] = block1[i]; - } else if (dct->format == SSE2_PERM) { - for (i = 0; i < 64; i++) - block[(i & 0x38) | idct_sse2_row_perm[i & 7]] = block1[i]; - } else if (dct->format == PARTTRANS_PERM) { - for (i = 0; i < 64; i++) - block[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = block1[i]; - } else { - for (i = 0; i < 64; i++) - block[i] = block1[i]; - } + init_block(block1, test, is_idct, &prng, vals); + permute(block, block1, dct->format); dct->func(block); mmx_emms(); @@ -317,45 +328,15 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed, c return 0; /* speed test */ - for (i = 0; i < 64; i++) - block1[i] = 0; - - switch (test) { - case 0: - for (i = 0; i < 64; i++) - block1[i] = av_lfg_get(&prng) % (2*vals) -vals; - if (is_idct) { - ff_ref_fdct(block1); - for (i = 0; i < 64; i++) - block1[i] >>= 3; - } - break; - case 1: - case 2: - block1[0] = av_lfg_get(&prng) % (2*vals) -vals; - block1[1] = av_lfg_get(&prng) % (2*vals) -vals; - block1[2] = av_lfg_get(&prng) % (2*vals) -vals; - block1[3] = av_lfg_get(&prng) % (2*vals) -vals; - break; - } - if (dct->format == MMX_PERM) { - for (i = 0; i < 64; i++) - block[idct_mmx_perm[i]] = block1[i]; - } else if (dct->format == MMX_SIMPLE_PERM) { - for (i = 0; i < 64; i++) - block[idct_simple_mmx_perm[i]] = block1[i]; - } else { - for (i = 0; i < 64; i++) - block[i] = block1[i]; - } + init_block(block, test, is_idct, &prng, vals); + permute(block1, block, dct->format); ti = gettime(); it1 = 0; do { for (it = 0; it < NB_ITS_SPEED; it++) { - for (i = 0; i < 64; i++) - block[i] = block1[i]; + memcpy(block, block1, sizeof(block)); dct->func(block); } it1 += NB_ITS_SPEED; diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index a526bc1c60..96ebb24027 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -620,8 +620,8 @@ retry: } MPV_frame_end(s); -assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type); -assert(s->current_picture.pict_type == s->pict_type); +assert(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type); +assert(s->current_picture.f.pict_type == s->pict_type); *pict= *(AVFrame*)s->current_picture_ptr; ff_print_debug_info(s, pict); diff --git a/libavcodec/h264.c b/libavcodec/h264.c index d4858d02ef..b21b7fc71a 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2774,7 +2774,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ if (s0->first_field) { assert(s0->current_picture_ptr); assert(s0->current_picture_ptr->f.data[0]); - assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF); + assert(s0->current_picture_ptr->f.reference != DELAYED_PIC_REF); /* figure out if we have a complementary field pair */ if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) { diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 691dcf9d57..ab9592bcea 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -172,7 +172,7 @@ static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ int mv[2]; int list; - assert(h->ref_list[1][0].reference&3); + assert(h->ref_list[1][0].f.reference & 3); await_reference_mb_row(h, &h->ref_list[1][0], s->mb_y + !!IS_INTERLACED(*mb_type)); @@ -416,7 +416,7 @@ static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ unsigned int sub_mb_type; int i8, i4; - assert(h->ref_list[1][0].reference&3); + assert(h->ref_list[1][0].f.reference & 3); await_reference_mb_row(h, &h->ref_list[1][0], s->mb_y + !!IS_INTERLACED(*mb_type)); diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 9134becb01..647f4a22f6 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1176,7 +1176,7 @@ static int mpeg_decode_update_thread_context(AVCodecContext *avctx, const AVCode if (!ctx->mpeg_enc_ctx_allocated) memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext)); - if (!(s->pict_type == FF_B_TYPE || s->low_delay)) + if (!(s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)) s->picture_number++; return 0; diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index e74d43adb8..da06bee28a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -225,7 +225,7 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic) int r; if (s->avctx->hwaccel) { - assert(!pic->hwaccel_picture_private); + assert(!pic->f.hwaccel_picture_private); if (s->avctx->hwaccel->priv_data_size) { pic->f.hwaccel_picture_private = av_mallocz(s->avctx->hwaccel->priv_data_size); if (!pic->f.hwaccel_picture_private) { @@ -276,7 +276,7 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared){ if(shared){ assert(pic->f.data[0]); - assert(pic->type == 0 || pic->type == FF_BUFFER_TYPE_SHARED); + assert(pic->f.type == 0 || pic->f.type == FF_BUFFER_TYPE_SHARED); pic->f.type = FF_BUFFER_TYPE_SHARED; }else{ assert(!pic->f.data[0]); @@ -539,7 +539,7 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src s->last_pict_type= s1->pict_type; if (s1->current_picture_ptr) s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f.quality; - if(s1->pict_type!=FF_B_TYPE){ + if (s1->pict_type != AV_PICTURE_TYPE_B) { s->last_non_b_pict_type= s1->pict_type; } } @@ -2662,6 +2662,6 @@ void ff_set_qscale(MpegEncContext * s, int qscale) void MPV_report_decode_progress(MpegEncContext *s) { - if (s->pict_type != FF_B_TYPE && !s->partitioned_frame && !s->error_occurred) + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->error_occurred) ff_thread_report_progress((AVFrame*)s->current_picture_ptr, s->mb_y, 0); } diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 610e683493..8fcb934a17 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1093,8 +1093,8 @@ static int select_input_picture(MpegEncContext *s){ s->input_picture[0]->f.data[i] = NULL; s->input_picture[0]->f.type = 0; }else{ - assert( s->input_picture[0]->type==FF_BUFFER_TYPE_USER - || s->input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL); + assert( s->input_picture[0]->f.type == FF_BUFFER_TYPE_USER + || s->input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL); s->avctx->release_buffer(s->avctx, (AVFrame*)s->input_picture[0]); } @@ -1220,8 +1220,8 @@ no_output_pic: }else{ // input is not a shared pix -> reuse buffer for current_pix - assert( s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_USER - || s->reordered_input_picture[0]->type==FF_BUFFER_TYPE_INTERNAL); + assert( s->reordered_input_picture[0]->f.type == FF_BUFFER_TYPE_USER + || s->reordered_input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL); s->current_picture_ptr= s->reordered_input_picture[0]; for(i=0; i<4; i++){ @@ -2757,7 +2757,7 @@ static int estimate_qp(MpegEncContext *s, int dry_run){ /* must be called before writing the header */ static void set_frame_distances(MpegEncContext * s){ - assert(s->current_picture_ptr->pts != AV_NOPTS_VALUE); + assert(s->current_picture_ptr->f.pts != AV_NOPTS_VALUE); s->time = s->current_picture_ptr->f.pts * s->avctx->time_base.num; if(s->pict_type==AV_PICTURE_TYPE_B){ diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 5ed03c4ddf..35ffb387a6 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -62,10 +62,6 @@ static uint32_t v2_dc_chroma_table[512][2]; /* vc1 externs */ extern const uint8_t wmv3_dc_scale_table[32]; -#ifdef DEBUG -int frame_count = 0; -#endif - #include "msmpeg4data.h" #if CONFIG_ENCODERS //strangely gcc includes this even if it is not referenced diff --git a/libavcodec/options.c b/libavcodec/options.c index b78ffccdba..eb69904c10 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -448,7 +448,7 @@ static const AVOption options[]={ {"request_channels", "set desired number of audio channels", OFFSET(request_channels), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, INT_MAX, A|D}, #endif #if FF_API_DRC_SCALE -{"drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), FF_OPT_TYPE_FLOAT, {.dbl = 1.0 }, 0.0, 1.0, A|D}, +{"drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), FF_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 1.0, A|D}, #endif #if FF_API_LAME_GLOBAL_OPTS {"reservoir", "use bit reservoir", 0, FF_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_BIT_RESERVOIR }, INT_MIN, INT_MAX, A|E, "flags2"}, @@ -544,7 +544,6 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_typ s->pix_fmt= PIX_FMT_NONE; s->sample_fmt= AV_SAMPLE_FMT_NONE; - s->palctrl = NULL; s->reget_buffer= avcodec_default_reget_buffer; s->reordered_opaque= AV_NOPTS_VALUE; } @@ -623,7 +622,6 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src) /* set values specific to opened codecs back to their default state */ dest->priv_data = NULL; dest->codec = NULL; - dest->palctrl = NULL; dest->slice_offset = NULL; dest->internal_buffer = NULL; dest->hwaccel = NULL; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 068d7272f6..a7bf93db81 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -85,6 +85,20 @@ AVCodec *av_codec_next(AVCodec *c){ else return first_avcodec; } +#if !FF_API_AVCODEC_INIT +static +#endif +void avcodec_init(void) +{ + static int initialized = 0; + + if (initialized != 0) + return; + initialized = 1; + + dsputil_static_init(); +} + void avcodec_register(AVCodec *codec) { AVCodec **p; @@ -1144,20 +1158,6 @@ const char *avcodec_license(void) return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; } -#if !FF_API_AVCODEC_INIT -static -#endif -void avcodec_init(void) -{ - static int initialized = 0; - - if (initialized != 0) - return; - initialized = 1; - - dsputil_static_init(); -} - void avcodec_flush_buffers(AVCodecContext *avctx) { if(HAVE_PTHREADS && avctx->active_thread_type&FF_THREAD_FRAME) diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c index 79faf8848d..1ed7b6ed5e 100644 --- a/libavdevice/alsa-audio-common.c +++ b/libavdevice/alsa-audio-common.c @@ -31,6 +31,7 @@ #include <alsa/asoundlib.h> #include "avdevice.h" #include "libavutil/avassert.h" +#include "libavutil/audioconvert.h" #include "alsa-audio.h" diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 930ab5c870..29ba1abc5e 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -66,63 +66,129 @@ static unsigned int get_size(AVIOContext *s, int len) return v; } -static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key) +/** + * Free GEOB type extra metadata. + */ +static void free_geobtag(ID3v2ExtraMetaGEOB *geob) { - char *q, dst[512]; - const char *val = NULL; - int len, dstlen = sizeof(dst) - 1; - unsigned genre; - unsigned int (*get)(AVIOContext*) = avio_rb16; + av_free(geob->mime_type); + av_free(geob->file_name); + av_free(geob->description); + av_free(geob->data); + av_free(geob); +} - dst[0] = 0; - if (taglen < 1) - return; +/** + * Decode characters to UTF-8 according to encoding type. The decoded buffer is + * always null terminated. + * + * @param dst Pointer where the address of the buffer with the decoded bytes is + * stored. Buffer must be freed by caller. + * @param dstlen Pointer to an int where the length of the decoded string + * is stored (in bytes, incl. null termination) + * @param maxread Pointer to maximum number of characters to read from the + * AVIOContext. After execution the value is decremented by the number of bytes + * actually read. + * @seeknull If true, decoding stops after the first U+0000 character found, if + * there is any before maxread is reached + * @returns 0 if no error occured, dst is uninitialized on error + */ +static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, + uint8_t **dst, int *dstlen, int *maxread, const int seeknull) +{ + int len, ret; + uint8_t tmp; + uint32_t ch = 1; + int left = *maxread; + unsigned int (*get)(AVIOContext*) = avio_rb16; + AVIOContext *dynbuf; - taglen--; /* account for encoding type byte */ + if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) { + av_log(s, AV_LOG_ERROR, "Error opening memory stream\n"); + return ret; + } - switch (avio_r8(pb)) { /* encoding type */ + switch (encoding) { case ID3v2_ENCODING_ISO8859: - q = dst; - while (taglen-- && q - dst < dstlen - 7) { - uint8_t tmp; - PUT_UTF8(avio_r8(pb), tmp, *q++ = tmp;) + while (left && (!seeknull || ch)) { + ch = avio_r8(pb); + PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);) + left--; } - *q = 0; break; case ID3v2_ENCODING_UTF16BOM: - taglen -= 2; + if ((left -= 2) < 0) { + av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n"); + avio_close_dyn_buf(dynbuf, (uint8_t **)dst); + av_freep(dst); + return AVERROR_INVALIDDATA; + } switch (avio_rb16(pb)) { case 0xfffe: get = avio_rl16; case 0xfeff: break; default: - av_log(s, AV_LOG_ERROR, "Incorrect BOM value in tag %s.\n", key); - return; + av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n"); + avio_close_dyn_buf(dynbuf, (uint8_t **)dst); + av_freep(dst); + *maxread = left; + return AVERROR_INVALIDDATA; } // fall-through case ID3v2_ENCODING_UTF16BE: - q = dst; - while (taglen > 1 && q - dst < dstlen - 7) { - uint32_t ch; - uint8_t tmp; - - GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;) - PUT_UTF8(ch, tmp, *q++ = tmp;) + while ((left > 1) && (!seeknull || ch)) { + GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;) + PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);) } - *q = 0; + if (left < 0) + left += 2; /* did not read last char from pb */ break; case ID3v2_ENCODING_UTF8: - len = FFMIN(taglen, dstlen); - avio_read(pb, dst, len); - dst[len] = 0; + while (left && (!seeknull || ch)) { + ch = avio_r8(pb); + avio_w8(dynbuf, ch); + left--; + } break; default: - av_log(s, AV_LOG_WARNING, "Unknown encoding in tag %s.\n", key); + av_log(s, AV_LOG_WARNING, "Unknown encoding\n"); + } + + if (ch) + avio_w8(dynbuf, 0); + + len = avio_close_dyn_buf(dynbuf, (uint8_t **)dst); + if (dstlen) + *dstlen = len; + + *maxread = left; + + return 0; +} + +/** + * Parse a text tag. + */ +static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key) +{ + uint8_t *dst; + const char *val = NULL; + int len, dstlen; + unsigned genre; + + if (taglen < 1) + return; + + taglen--; /* account for encoding type byte */ + + if (decode_str(s, pb, avio_r8(pb), &dst, &dstlen, &taglen, 0) < 0) { + av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key); + return; } if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) @@ -141,6 +207,82 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const cha if (val) av_dict_set(&s->metadata, key, val, AV_DICT_DONT_OVERWRITE); + + av_free(dst); +} + +/** + * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct. + */ +static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta) +{ + ID3v2ExtraMetaGEOB *geob_data = NULL; + ID3v2ExtraMeta *new_extra = NULL; + char encoding; + unsigned int len; + + if (taglen < 1) + return; + + geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB)); + if (!geob_data) { + av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMetaGEOB)); + return; + } + + new_extra = av_mallocz(sizeof(ID3v2ExtraMeta)); + if (!new_extra) { + av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMeta)); + goto fail; + } + + /* read encoding type byte */ + encoding = avio_r8(pb); + taglen--; + + /* read MIME type (always ISO-8859) */ + if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, NULL, &taglen, 1) < 0 + || taglen <= 0) + goto fail; + + /* read file name */ + if (decode_str(s, pb, encoding, &geob_data->file_name, NULL, &taglen, 1) < 0 + || taglen <= 0) + goto fail; + + /* read content description */ + if (decode_str(s, pb, encoding, &geob_data->description, NULL, &taglen, 1) < 0 + || taglen < 0) + goto fail; + + if (taglen) { + /* save encapsulated binary data */ + geob_data->data = av_malloc(taglen); + if (!geob_data->data) { + av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", taglen); + goto fail; + } + if ((len = avio_read(pb, geob_data->data, taglen)) < taglen) + av_log(s, AV_LOG_WARNING, "Error reading GEOB frame, data truncated.\n"); + geob_data->datasize = len; + } else { + geob_data->data = NULL; + geob_data->datasize = 0; + } + + /* add data to the list */ + new_extra->tag = "GEOB"; + new_extra->data = geob_data; + new_extra->next = *extra_meta; + *extra_meta = new_extra; + + return; + +fail: + av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", tag); + free_geobtag(geob_data); + av_free(new_extra); + return; } static int is_number(const char *str) @@ -189,7 +331,27 @@ finish: av_dict_set(m, "date", date, 0); } -static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags) +/** + * Get the corresponding ID3v2EMFunc struct for a tag. + * @param isv34 Determines if v2.2 or v2.3/4 strings are used + * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise. + */ +static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34) +{ + int i = 0; + while (ff_id3v2_extra_meta_funcs[i].tag3) { + if (!memcmp(tag, + (isv34 ? + ff_id3v2_extra_meta_funcs[i].tag4 : + ff_id3v2_extra_meta_funcs[i].tag3), + (isv34 ? 4 : 3))) + return &ff_id3v2_extra_meta_funcs[i]; + i++; + } + return NULL; +} + +static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags, ID3v2ExtraMeta **extra_meta) { int isv34, unsync; unsigned tlen; @@ -198,8 +360,10 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t int taghdrlen; const char *reason = NULL; AVIOContext pb; + AVIOContext *pbx; unsigned char *buffer = NULL; int buffer_size = 0; + void (*extra_func)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta**) = NULL; switch (version) { case 2: @@ -264,7 +428,8 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) { av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed ID3v2 frame %s.\n", tag); avio_skip(s->pb, tlen); - } else if (tag[0] == 'T') { + /* check for text tag or supported special meta tag */ + } else if (tag[0] == 'T' || (extra_meta && (extra_func = get_extra_meta_func(tag, isv34)->read))) { if (unsync || tunsync) { int i, j; av_fast_malloc(&buffer, &buffer_size, tlen); @@ -280,10 +445,17 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t } } ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL); - read_ttag(s, &pb, j, tag); + tlen = j; + pbx = &pb; // read from sync buffer } else { - read_ttag(s, s->pb, tlen, tag); + pbx = s->pb; // read straight from input } + if (tag[0] == 'T') + /* parse text tag */ + read_ttag(s, pbx, tlen, tag); + else + /* parse special meta tag */ + extra_func(s, pbx, tlen, tag, extra_meta); } else if (!tag[0]) { if (tag[1]) @@ -307,7 +479,7 @@ seek: return; } -void ff_id3v2_read(AVFormatContext *s, const char *magic) +void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta) { int len, ret; uint8_t buf[ID3v2_HEADER_SIZE]; @@ -327,7 +499,7 @@ void ff_id3v2_read(AVFormatContext *s, const char *magic) ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f); - ff_id3v2_parse(s, len, buf[3], buf[5]); + ff_id3v2_parse(s, len, buf[3], buf[5], extra_meta); } else { avio_seek(s->pb, off, SEEK_SET); } @@ -338,6 +510,30 @@ void ff_id3v2_read(AVFormatContext *s, const char *magic) merge_date(&s->metadata); } +void ff_id3v2_read(AVFormatContext *s, const char *magic) +{ + ff_id3v2_read_all(s, magic, NULL); +} + +void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta) +{ + ID3v2ExtraMeta *current = *extra_meta, *next; + void (*free_func)(ID3v2ExtraMeta*); + + while (current) { + if ((free_func = get_extra_meta_func(current->tag, 1)->free)) + free_func(current->data); + next = current->next; + av_freep(¤t); + current = next; + } +} + +const ID3v2EMFunc ff_id3v2_extra_meta_funcs[] = { + { "GEO", "GEOB", read_geobtag, free_geobtag }, + { NULL } +}; + const AVMetadataConv ff_id3v2_34_metadata_conv[] = { { "TALB", "album"}, { "TCOM", "composer"}, diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index e429001385..a30a74f5fd 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -45,6 +45,27 @@ enum ID3v2Encoding { ID3v2_ENCODING_UTF8 = 3, }; +typedef struct ID3v2ExtraMeta { + const char *tag; + void *data; + struct ID3v2ExtraMeta *next; +} ID3v2ExtraMeta; + +typedef struct ID3v2ExtraMetaGEOB { + uint32_t datasize; + uint8_t *mime_type; + uint8_t *file_name; + uint8_t *description; + uint8_t *data; +} ID3v2ExtraMetaGEOB; + +typedef struct ID3v2EMFunc { + const char *tag3; + const char *tag4; + void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **); + void (*free)(); +} ID3v2EMFunc; + /** * Detect ID3v2 Header. * @param buf must be ID3v2_HEADER_SIZE byte long @@ -61,10 +82,25 @@ int ff_id3v2_match(const uint8_t *buf, const char *magic); int ff_id3v2_tag_len(const uint8_t *buf); /** - * Read an ID3v2 tag + * Read an ID3v2 tag (text tags only) */ void ff_id3v2_read(AVFormatContext *s, const char *magic); +/** + * Read an ID3v2 tag, including supported extra metadata (currently only GEOB) + * @param extra_meta If not NULL, extra metadata is parsed into a list of + * ID3v2ExtraMeta structs and *extra_meta points to the head of the list + */ +void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta); + +/** + * Free memory allocated parsing special (non-text) metadata. + * @param extra_meta Pointer to a pointer to the head of a ID3v2ExtraMeta list, *extra_meta is set to NULL. + */ +void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta); + +extern const ID3v2EMFunc ff_id3v2_extra_meta_funcs[]; + extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; extern const AVMetadataConv ff_id3v2_2_metadata_conv[]; diff --git a/libavformat/mov.c b/libavformat/mov.c index 70cd776496..5f91e7d50c 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2629,8 +2629,6 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->drefs); if (sc->pb && sc->pb != s->pb) avio_close(sc->pb); - - av_freep(&st->codec->palctrl); } if (mov->dv_demux) { diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index d3f40aa892..02f0d56e5a 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1444,7 +1444,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) if (avio_tell(s->pb) != ts->last_pos) { int i; -// av_dlog("Skipping after seek\n"); + av_dlog(ts->stream, "Skipping after seek\n"); /* seek detected, flush pes buffer */ for (i = 0; i < NB_PID_MAX; i++) { if (ts->pids[i]) { diff --git a/libavformat/oma.c b/libavformat/oma.c index 1ab30688c6..09fa2ca985 100644 --- a/libavformat/oma.c +++ b/libavformat/oma.c @@ -3,6 +3,7 @@ * * Copyright (c) 2008 Maxim Poliakovski * 2008 Benjamin Larsson + * 2011 David Goldwich * * This file is part of FFmpeg. * @@ -36,20 +37,19 @@ * - Sound data organized in packets follow the EA3 header * (can be encrypted using the Sony DRM!). * - * LIMITATIONS: This version supports only plain (unencrypted) OMA files. - * If any DRM-protected (encrypted) file is encountered you will get the - * corresponding error message. Try to remove the encryption using any - * Sony software (for example SonicStage). * CODEC SUPPORT: Only ATRAC3 codec is currently supported! */ #include "avformat.h" #include "libavutil/intreadwrite.h" +#include "libavutil/des.h" #include "pcm.h" #include "riff.h" #include "id3v2.h" #define EA3_HEADER_SIZE 96 +#define ID3v2_EA3_MAGIC "ea3" +#define OMA_ENC_HEADER_SIZE 16 enum { OMA_CODECID_ATRAC3 = 0, @@ -65,7 +65,211 @@ static const AVCodecTag codec_oma_tags[] = { { CODEC_ID_MP3, OMA_CODECID_MP3 }, }; -#define ID3v2_EA3_MAGIC "ea3" +static const uint64_t leaf_table[] = { + 0xd79e8283acea4620, 0x7a9762f445afd0d8, + 0x354d60a60b8c79f1, 0x584e1cde00b07aee, + 0x1573cd93da7df623, 0x47f98d79620dd535 +}; + +typedef struct OMAContext { + uint64_t content_start; + int encrypted; + uint16_t k_size; + uint16_t e_size; + uint16_t i_size; + uint16_t s_size; + uint32_t rid; + uint8_t r_val[24]; + uint8_t n_val[24]; + uint8_t m_val[8]; + uint8_t s_val[8]; + uint8_t sm_val[8]; + uint8_t e_val[8]; + uint8_t iv[8]; + struct AVDES av_des; +} OMAContext; + +static void hex_log(AVFormatContext *s, int level, const char *name, const uint8_t *value, int len) +{ + char buf[33]; + len = FFMIN(len, 16); + if (av_log_get_level() < level) + return; + ff_data_to_hex(buf, value, len, 1); + buf[len<<1] = '\0'; + av_log(s, level, "%s: %s\n", name, buf); +} + +static int kset(AVFormatContext *s, const uint8_t *r_val, const uint8_t *n_val, int len) +{ + OMAContext *oc = s->priv_data; + + if (!r_val && !n_val) + return -1; + + len = FFMIN(len, 16); + + /* use first 64 bits in the third round again */ + if (r_val) { + if (r_val != oc->r_val) { + memset(oc->r_val, 0, 24); + memcpy(oc->r_val, r_val, len); + } + memcpy(&oc->r_val[16], r_val, 8); + } + if (n_val) { + if (n_val != oc->n_val) { + memset(oc->n_val, 0, 24); + memcpy(oc->n_val, n_val, len); + } + memcpy(&oc->n_val[16], n_val, 8); + } + + return 0; +} + +static int rprobe(AVFormatContext *s, uint8_t *enc_header, const uint8_t *r_val) +{ + OMAContext *oc = s->priv_data; + unsigned int pos; + struct AVDES av_des; + + if (!enc_header || !r_val) + return -1; + + /* m_val */ + av_des_init(&av_des, r_val, 192, 1); + av_des_crypt(&av_des, oc->m_val, &enc_header[48], 1, NULL, 1); + + /* s_val */ + av_des_init(&av_des, oc->m_val, 64, 0); + av_des_crypt(&av_des, oc->s_val, NULL, 1, NULL, 0); + + /* sm_val */ + pos = OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size; + av_des_init(&av_des, oc->s_val, 64, 0); + av_des_mac(&av_des, oc->sm_val, &enc_header[pos], (oc->i_size >> 3)); + + pos += oc->i_size; + + return memcmp(&enc_header[pos], oc->sm_val, 8) ? -1 : 0; +} + +static int nprobe(AVFormatContext *s, uint8_t *enc_header, const uint8_t *n_val) +{ + OMAContext *oc = s->priv_data; + uint32_t pos, taglen, datalen; + struct AVDES av_des; + + if (!enc_header || !n_val) + return -1; + + pos = OMA_ENC_HEADER_SIZE + oc->k_size; + if (!memcmp(&enc_header[pos], "EKB ", 4)) + pos += 32; + + if (AV_RB32(&enc_header[pos]) != oc->rid) + av_log(s, AV_LOG_DEBUG, "Mismatching RID\n"); + + taglen = AV_RB32(&enc_header[pos+32]); + datalen = AV_RB32(&enc_header[pos+36]) >> 4; + + pos += 44 + taglen; + + av_des_init(&av_des, n_val, 192, 1); + while (datalen-- > 0) { + av_des_crypt(&av_des, oc->r_val, &enc_header[pos], 2, NULL, 1); + kset(s, oc->r_val, NULL, 16); + if (!rprobe(s, enc_header, oc->r_val)) + return 0; + pos += 16; + } + + return -1; +} + +static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) +{ + OMAContext *oc = s->priv_data; + ID3v2ExtraMetaGEOB *geob = NULL; + uint8_t *gdata; + + oc->encrypted = 1; + av_log(s, AV_LOG_INFO, "File is encrypted\n"); + + /* find GEOB metadata */ + while (em) { + if (!strcmp(em->tag, "GEOB") && + (geob = em->data) && + !strcmp(geob->description, "OMG_LSI") || + !strcmp(geob->description, "OMG_BKLSI")) { + break; + } + em = em->next; + } + if (!em) { + av_log(s, AV_LOG_ERROR, "No encryption header found\n"); + return -1; + } + + if (geob->datasize < 64) { + av_log(s, AV_LOG_ERROR, "Invalid GEOB data size: %u\n", geob->datasize); + return -1; + } + + gdata = geob->data; + + if (AV_RB16(gdata) != 1) + av_log(s, AV_LOG_WARNING, "Unknown version in encryption header\n"); + + oc->k_size = AV_RB16(&gdata[2]); + oc->e_size = AV_RB16(&gdata[4]); + oc->i_size = AV_RB16(&gdata[6]); + oc->s_size = AV_RB16(&gdata[8]); + + if (memcmp(&gdata[OMA_ENC_HEADER_SIZE], "KEYRING ", 12)) { + av_log(s, AV_LOG_ERROR, "Invalid encryption header\n"); + return -1; + } + oc->rid = AV_RB32(&gdata[OMA_ENC_HEADER_SIZE + 28]); + av_log(s, AV_LOG_DEBUG, "RID: %.8x\n", oc->rid); + + memcpy(oc->iv, &header[0x58], 8); + hex_log(s, AV_LOG_DEBUG, "IV", oc->iv, 8); + + hex_log(s, AV_LOG_DEBUG, "CBC-MAC", &gdata[OMA_ENC_HEADER_SIZE+oc->k_size+oc->e_size+oc->i_size], 8); + + if (s->keylen > 0) { + kset(s, s->key, s->key, s->keylen); + } + if (!memcmp(oc->r_val, (const uint8_t[8]){0}, 8) || + rprobe(s, gdata, oc->r_val) < 0 && + nprobe(s, gdata, oc->n_val) < 0) { + int i; + for (i = 0; i < sizeof(leaf_table); i += 2) { + uint8_t buf[16]; + AV_WL64(buf, leaf_table[i]); + AV_WL64(&buf[8], leaf_table[i+1]); + kset(s, buf, buf, 16); + if (!rprobe(s, gdata, oc->r_val) || !nprobe(s, gdata, oc->n_val)) + break; + } + if (i >= sizeof(leaf_table)) { + av_log(s, AV_LOG_ERROR, "Invalid key\n"); + return -1; + } + } + + /* e_val */ + av_des_init(&oc->av_des, oc->m_val, 64, 0); + av_des_crypt(&oc->av_des, oc->e_val, &gdata[OMA_ENC_HEADER_SIZE + 40], 1, NULL, 0); + hex_log(s, AV_LOG_DEBUG, "EK", oc->e_val, 8); + + /* init e_val */ + av_des_init(&oc->av_des, oc->e_val, 64, 1); + + return 0; +} static int oma_read_header(AVFormatContext *s, AVFormatParameters *ap) @@ -77,8 +281,10 @@ static int oma_read_header(AVFormatContext *s, uint8_t buf[EA3_HEADER_SIZE]; uint8_t *edata; AVStream *st; + ID3v2ExtraMeta *extra_meta = NULL; + OMAContext *oc = s->priv_data; - ff_id3v2_read(s, ID3v2_EA3_MAGIC); + ff_id3v2_read_all(s, ID3v2_EA3_MAGIC, &extra_meta); ret = avio_read(s->pb, buf, EA3_HEADER_SIZE); if (ret < EA3_HEADER_SIZE) return -1; @@ -88,12 +294,17 @@ static int oma_read_header(AVFormatContext *s, return -1; } + oc->content_start = avio_tell(s->pb); + + /* encrypted file */ eid = AV_RB16(&buf[6]); - if (eid != -1 && eid != -128) { - av_log(s, AV_LOG_ERROR, "Encrypted file! Eid: %d\n", eid); + if (eid != -1 && eid != -128 && decrypt_init(s, extra_meta, buf) < 0) { + ff_id3v2_free_extra_meta(&extra_meta); return -1; } + ff_id3v2_free_extra_meta(&extra_meta); + codec_params = AV_RB24(&buf[33]); st = av_new_stream(s, 0); @@ -159,12 +370,20 @@ static int oma_read_header(AVFormatContext *s, static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) { - int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align); + OMAContext *oc = s->priv_data; + int packet_size = s->streams[0]->codec->block_align; + int ret = av_get_packet(s->pb, pkt, packet_size); - pkt->stream_index = 0; if (ret <= 0) return AVERROR(EIO); + pkt->stream_index = 0; + + if (oc->encrypted) { + /* previous unencrypted block saved in IV for the next packet (CBC mode) */ + av_des_crypt(&oc->av_des, pkt->data, pkt->data, (packet_size >> 3), oc->iv, 1); + } + return ret; } @@ -190,16 +409,38 @@ static int oma_read_probe(AVProbeData *p) return 0; } +static int oma_read_seek(struct AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + OMAContext *oc = s->priv_data; + + pcm_read_seek(s, stream_index, timestamp, flags); + + if (oc->encrypted) { + /* readjust IV for CBC */ + int64_t pos = avio_tell(s->pb); + if (pos < oc->content_start) + memset(oc->iv, 0, 8); + else { + if (avio_seek(s->pb, -8, SEEK_CUR) < 0 || avio_read(s->pb, oc->iv, 8) < 8) { + memset(oc->iv, 0, 8); + return -1; + } + } + } + + return 0; +} AVInputFormat ff_oma_demuxer = { .name = "oma", .long_name = NULL_IF_CONFIG_SMALL("Sony OpenMG audio"), + .priv_data_size = sizeof(OMAContext), .read_probe = oma_read_probe, .read_header = oma_read_header, .read_packet = oma_read_packet, - .read_seek = pcm_read_seek, - .flags= AVFMT_GENERIC_INDEX, - .extensions = "oma,aa3", - .codec_tag= (const AVCodecTag* const []){codec_oma_tags, 0}, + .read_seek = oma_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "oma,omg,aa3", + .codec_tag = (const AVCodecTag* const []){codec_oma_tags, 0}, }; diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index d399cc3a5d..7bbf494e99 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -136,8 +136,9 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) ast->need_parsing = AVSTREAM_PARSE_FULL; sample_rate_code= (v>>2) & 3; if (!sample_rate_code) - return AVERROR(EIO); - ast->codec->sample_rate = 11025 << (sample_rate_code-1); + ast->codec->sample_rate = 5512; + else + ast->codec->sample_rate = 11025 << (sample_rate_code-1); av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); len -= 4; } else if (tag == TAG_VIDEOFRAME) { diff --git a/libavutil/des.c b/libavutil/des.c index f6643696d6..b876dccd53 100644 --- a/libavutil/des.c +++ b/libavutil/des.c @@ -298,7 +298,7 @@ int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) { return 0; } -void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) { +static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt, int mac) { uint64_t iv_val = iv ? AV_RB64(iv) : 0; while (count-- > 0) { uint64_t dst_val; @@ -321,12 +321,21 @@ void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t } AV_WB64(dst, dst_val); src += 8; - dst += 8; + if (!mac) + dst += 8; } if (iv) AV_WB64(iv, iv_val); } +void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) { + av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0); +} + +void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) { + av_des_crypt_mac(d, dst, src, count, (uint8_t[8]){0}, 0, 1); +} + #ifdef TEST #undef printf #undef rand diff --git a/libavutil/des.h b/libavutil/des.h index dd670869b2..2feb0468db 100644 --- a/libavutil/des.h +++ b/libavutil/des.h @@ -33,7 +33,7 @@ struct AVDES { * @brief Initializes an AVDES context. * * @param key_bits must be 64 or 192 - * @param decrypt 0 for encryption, 1 for decryption + * @param decrypt 0 for encryption/CBC-MAC, 1 for decryption */ int av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt); @@ -49,4 +49,13 @@ int av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt); */ void av_des_crypt(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt); +/** + * @brief Calculates CBC-MAC using the DES algorithm. + * + * @param count number of 8 byte blocks + * @param dst destination array, can be equal to src, must be 8-byte aligned + * @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL + */ +void av_des_mac(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count); + #endif /* AVUTIL_DES_H */ |