summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/developer.texi2
-rw-r--r--libavcodec/ac3dec.c7
-rw-r--r--libavcodec/avcodec.h4
-rw-r--r--libavcodec/dct-test.c127
-rw-r--r--libavcodec/h261dec.c4
-rw-r--r--libavcodec/h264.c2
-rw-r--r--libavcodec/h264_direct.c4
-rw-r--r--libavcodec/mpeg12.c2
-rw-r--r--libavcodec/mpegvideo.c8
-rw-r--r--libavcodec/mpegvideo_enc.c10
-rw-r--r--libavcodec/msmpeg4.c4
-rw-r--r--libavcodec/options.c4
-rw-r--r--libavcodec/utils.c28
-rw-r--r--libavdevice/alsa-audio-common.c1
-rw-r--r--libavformat/id3v2.c270
-rw-r--r--libavformat/id3v2.h38
-rw-r--r--libavformat/mov.c2
-rw-r--r--libavformat/mpegts.c2
-rw-r--r--libavformat/oma.c269
-rw-r--r--libavformat/swfdec.c5
-rw-r--r--libavutil/des.c13
-rw-r--r--libavutil/des.h11
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(&current);
+ 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 */