From b3e144a7dfc6953df3b3e478eb8b8521ab5c6ecc Mon Sep 17 00:00:00 2001 From: David Goldwich Date: Fri, 2 Sep 2011 08:20:58 +0200 Subject: [PATCH 01/19] des: add possibility to calculate DES-CBC-MAC with small buffer This patch adds the possibility to calculate the DES-CBC-MAC of a source buffer (i.e. the last block of the buffer encrypted in CBC mode) without having to allocate a destination buffer that is as long as the complete source buffer, but instead only 8 bytes for the MAC. Signed-off-by: David Goldwich Signed-off-by: Anton Khirnov --- libavutil/des.c | 13 +++++++++++-- libavutil/des.h | 11 ++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libavutil/des.c b/libavutil/des.c index d3f715e8fc..d65760e575 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 935d7c5d71..cda98122d3 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 */ From 7a019dffe568e4d58cf1b8b2216f8678e45066b9 Mon Sep 17 00:00:00 2001 From: David Goldwich Date: Sun, 18 Sep 2011 18:04:34 +0200 Subject: [PATCH 02/19] id3v2: add support for non-text and GEOB type tag frames This extends the ID3v2 parser to allow for reading of non-text (i.e. other than T***) meta tag frames providing a ff_id3v2_read_all() function. An additional data structure 'ID3v2ExtraMeta' is introduced for these tags since AVDictionary is string oriented and unsuitable for binary data. A parser for tag frames of type GEOB is implemented, which is needed to extract keyring information from encrypted OMA files. GEOB data is parsed into 'ID3v2ExtraMetaGEOB' data structures. The routine to decode characters from different encodings to UTF-8, formerly part of the read_ttag() function, is moved to its own function. Because some tag frames contain subparts of unknown length, the function is now also able to read until a null character is found. In addition, the function now takes care of allocating a buffer long enough to hold the decoded characters. Signed-off-by: David Goldwich Signed-off-by: Anton Khirnov --- libavformat/id3v2.c | 270 ++++++++++++++++++++++++++++++++++++++------ libavformat/id3v2.h | 38 ++++++- 2 files changed, 270 insertions(+), 38 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index be6c03bbe5..68c1709b93 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -59,63 +59,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; + av_free(geob->mime_type); + av_free(geob->file_name); + av_free(geob->description); + av_free(geob->data); + av_free(geob); +} + +/** + * 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; - dst[0] = 0; - if (taglen < 1) - return; + if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) { + av_log(s, AV_LOG_ERROR, "Error opening memory stream\n"); + return ret; + } - taglen--; /* account for encoding type byte */ - - 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")) @@ -134,6 +200,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) @@ -182,7 +324,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, tlen, unsync; char tag[5]; @@ -190,8 +352,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: @@ -252,7 +416,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); @@ -268,10 +433,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]) @@ -295,7 +467,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]; @@ -315,7 +487,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); } @@ -326,6 +498,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 3e0e65a92e..13dec399d1 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[]; From 61f4387d390c22d52153daac230ab2bc68114721 Mon Sep 17 00:00:00 2001 From: David Goldwich Date: Sun, 18 Sep 2011 21:58:09 +0200 Subject: [PATCH 03/19] oma: support for encrypted files Signed-off-by: David Goldwich Signed-off-by: Anton Khirnov --- libavformat/oma.c | 269 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 255 insertions(+), 14 deletions(-) diff --git a/libavformat/oma.c b/libavformat/oma.c index 7675841792..5ffe8fa9f0 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 Libav. * @@ -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}, }; From 5feb67f8a1a17a4dd3cec0aa80ef0dc543fc7673 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Thu, 14 Jul 2011 22:31:37 +0200 Subject: [PATCH 04/19] vf_yadif: copy buffer properties like aspect for second frame as well Signed-off-by: Anton Khirnov --- libavfilter/vf_yadif.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index aa5c434af9..2ba173970c 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -203,9 +203,12 @@ static void return_frame(AVFilterContext *ctx, int is_second) tff = yadif->parity^1; } - if (is_second) + if (is_second) { yadif->out = avfilter_get_video_buffer(link, AV_PERM_WRITE | AV_PERM_PRESERVE | AV_PERM_REUSE, link->w, link->h); + avfilter_copy_buffer_ref_props(yadif->out, yadif->cur); + yadif->out->video->interlaced = 0; + } if (!yadif->csp) yadif->csp = &av_pix_fmt_descriptors[link->format]; From 4703a7b50b098a53ec2f806bd41a00fd87ea9d8c Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Thu, 4 Aug 2011 00:25:35 +0200 Subject: [PATCH 05/19] vf_yadif: correct documentation on the parity parameter 0 is top-field-first, 1 is bottom-field-first, not the other way around. Signed-off-by: Anton Khirnov --- doc/filters.texi | 4 ++-- libavfilter/vf_yadif.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index f0a43813b6..2967db14d2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1527,9 +1527,9 @@ interlaced video, accepts one of the following values: @table @option @item 0 -assume bottom field first -@item 1 assume top field first +@item 1 +assume bottom field first @item -1 enable automatic detection @end table diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 2ba173970c..7a5b98e483 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -38,8 +38,8 @@ typedef struct { int mode; /** - * 0: bottom field first - * 1: top field first + * 0: top field first + * 1: bottom field first * -1: auto-detection */ int parity; From be4e8908d2ccc80a0603514b95499cd4380e8f81 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sat, 27 Aug 2011 18:32:14 +0200 Subject: [PATCH 06/19] vf_yadif: add support to yuva420p Signed-off-by: Anton Khirnov --- libavfilter/vf_yadif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 7a5b98e483..64b25616ea 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -147,7 +147,7 @@ static void filter(AVFilterContext *ctx, AVFilterBufferRef *dstpic, int refs = yadif->cur->linesize[i]; int df = (yadif->csp->comp[i].depth_minus1+1) / 8; - if (i) { + if (i == 1 || i == 2) { /* Why is this not part of the per-plane description thing? */ w >>= yadif->csp->log2_chroma_w; h >>= yadif->csp->log2_chroma_h; @@ -357,6 +357,7 @@ static int query_formats(AVFilterContext *ctx) AV_NE( PIX_FMT_YUV420P16BE, PIX_FMT_YUV420P16LE ), AV_NE( PIX_FMT_YUV422P16BE, PIX_FMT_YUV422P16LE ), AV_NE( PIX_FMT_YUV444P16BE, PIX_FMT_YUV444P16LE ), + PIX_FMT_YUVA420P, PIX_FMT_NONE }; From 35a68558688fb6fa62261008e93bd16544fbd37e Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 13 Sep 2011 17:00:16 +0200 Subject: [PATCH 07/19] Fix av_dlog invocations with wrong or missing logging context. This fixes build failures with -DDEBUG in CPPFLAGS. --- libavcodec/flashsvenc.c | 2 +- libavformat/mpegts.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index 6dc33b91f9..81aa5b6bfb 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -176,7 +176,7 @@ static int encode_bitstream(FlashSVContext *s, AVFrame *p, uint8_t *buf, bytestream_put_be16(&ptr, zsize); buf_pos += zsize + 2; - av_dlog(avctx, "buf_pos = %d\n", buf_pos); + av_dlog(s->avctx, "buf_pos = %d\n", buf_pos); } else { pred_blocks++; bytestream_put_be16(&ptr, 0); diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 16f69328a0..c625552600 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1409,7 +1409,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]) { From 95a06eb4d59c5ab0ce53b0cc9d10d1b26be939e2 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 13 Sep 2011 17:00:41 +0200 Subject: [PATCH 08/19] Fix assert() calls that need updates after FF_COMMON_FRAME macro elimination. This fixes build failures with -DDEBUG in CPPFLAGS. --- libavcodec/h261dec.c | 4 ++-- libavcodec/h264.c | 2 +- libavcodec/h264_direct.c | 4 ++-- libavcodec/mpegvideo.c | 4 ++-- libavcodec/mpegvideo_enc.c | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 63a153f06d..00375ef4fe 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 d0474489d9..9889224abd 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -2722,7 +2722,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 c73aab3d01..4e05937ab4 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/mpegvideo.c b/libavcodec/mpegvideo.c index 8d40492346..6839186aac 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]); diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 809ede1d9a..cad267b663 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){ From a3e0135dbb970a1bf2d9843d376d33f2b404bb88 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 20 Sep 2011 09:10:41 +0200 Subject: [PATCH 09/19] msmpeg4: remove leftover unused debug variable declaration --- libavcodec/msmpeg4.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index d773c3838b..eca2add828 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 From 4d77d57d20e5ccabd92603e5a5f20c192f1e1675 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 16:31:02 +0200 Subject: [PATCH 10/19] alsa: add missing header Fixes compile with next lavc major. --- libavdevice/alsa-audio-common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c index 126695f754..a0662f6d8e 100644 --- a/libavdevice/alsa-audio-common.c +++ b/libavdevice/alsa-audio-common.c @@ -31,6 +31,7 @@ #include #include "libavformat/avformat.h" #include "libavutil/avassert.h" +#include "libavutil/audioconvert.h" #include "alsa-audio.h" From 63e4c8a65316bb897f2c80cdac66b6f172c0f849 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 16:40:18 +0200 Subject: [PATCH 11/19] lavc: undeprecate AVPALETTE_SIZE and AVPALETTE_COUNT macros They are still being used and shouldn't be removed. --- libavcodec/avcodec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7fc0e545fc..a7defa0c4c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3082,6 +3082,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 @@ -3091,8 +3093,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; From feedc0754bd9fbdb1ae3453bc0555513e61d9e8d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 16:48:29 +0200 Subject: [PATCH 12/19] ac3dec: actually use drc_scale private option --- libavcodec/ac3dec.c | 7 ++++++- libavcodec/options.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 9c0ed7dccb..79360c2253 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/options.c b/libavcodec/options.c index 5cd5cab708..6469ea7e73 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -447,7 +447,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"}, From e5b29c1f6b5cd17ba4f0a976a535c4003a07eb02 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 16:57:20 +0200 Subject: [PATCH 13/19] lavc: replace some deprecated FF_*_TYPE with AV_PICTURE_TYPE_* --- libavcodec/dpxenc.c | 2 +- libavcodec/mpeg12.c | 2 +- libavcodec/mpegvideo.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c index 7ae929238d..1ff9d97fae 100644 --- a/libavcodec/dpxenc.c +++ b/libavcodec/dpxenc.c @@ -35,7 +35,7 @@ static av_cold int encode_init(AVCodecContext *avctx) DPXContext *s = avctx->priv_data; avctx->coded_frame = &s->picture; - avctx->coded_frame->pict_type = FF_I_TYPE; + avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; s->big_endian = 1; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index b4a83b45dc..6a12344139 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1167,7 +1167,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 6839186aac..e418e95a33 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -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; } } @@ -2652,6 +2652,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); } From 9ecfbb3e57dc1d46986b9296bf582c8e82b303b6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 16:59:35 +0200 Subject: [PATCH 14/19] lavc/utils: move avcodec_init() higher in the file. Fixes build on next major bump. --- libavcodec/utils.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 166fbec607..9f198cb32a 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; @@ -1065,20 +1079,6 @@ const char *avcodec_license(void) return LICENSE_PREFIX LIBAV_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) From 609a2fa1faa82da2451191170ce1807c9a1ba8a8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 17:01:53 +0200 Subject: [PATCH 15/19] Remove some forgotten AVCodecContext.palctrl usage. --- libavcodec/options.c | 2 -- libavformat/mov.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/libavcodec/options.c b/libavcodec/options.c index 6469ea7e73..ef711bf394 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -536,7 +536,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; } @@ -615,7 +614,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/libavformat/mov.c b/libavformat/mov.c index 35cd9a880b..3190afd120 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2591,8 +2591,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) { From 9aa1f87dfd815cfc3b1ba7db78da4bdf3a176053 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 11 Sep 2011 12:27:51 +0200 Subject: [PATCH 16/19] Revert "ffmpeg: get rid of useless AVInputStream.nb_streams." This reverts commit 2cf8355f98681bdd726b739008acd5483f82f8d7. AVInputStream.nb_streams tracks number of streams found at the beginning, new streams may appear that ffmpeg doesn't know about. Fixes crash in this case. --- ffmpeg.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index a440b9dacb..2a921d068d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -322,6 +322,7 @@ typedef struct InputFile { int ist_index; /* index of first stream in ist_table */ int buffer_size; /* current total buffer size */ int64_t ts_offset; + int nb_streams; /* nb streams we are aware of */ } InputFile; static InputStream *input_streams = NULL; @@ -1968,7 +1969,7 @@ static int transcode(AVFormatContext **output_files, int si = stream_maps[i].stream_index; if (fi < 0 || fi > nb_input_files - 1 || - si < 0 || si > input_files[fi].ctx->nb_streams - 1) { + si < 0 || si > input_files[fi].nb_streams - 1) { fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si); ret = AVERROR(EINVAL); goto fail; @@ -1976,7 +1977,7 @@ static int transcode(AVFormatContext **output_files, fi = stream_maps[i].sync_file_index; si = stream_maps[i].sync_stream_index; if (fi < 0 || fi > nb_input_files - 1 || - si < 0 || si > input_files[fi].ctx->nb_streams - 1) { + si < 0 || si > input_files[fi].nb_streams - 1) { fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si); ret = AVERROR(EINVAL); goto fail; @@ -2600,7 +2601,7 @@ static int transcode(AVFormatContext **output_files, } /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ - if (pkt.stream_index >= input_files[file_index].ctx->nb_streams) + if (pkt.stream_index >= input_files[file_index].nb_streams) goto discard_packet; ist_index = input_files[file_index].ist_index + pkt.stream_index; ist = &input_streams[ist_index]; @@ -3326,6 +3327,7 @@ static int opt_input_file(const char *opt, const char *filename) input_files[nb_input_files - 1].ctx = ic; input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams; input_files[nb_input_files - 1].ts_offset = input_ts_offset - (copy_ts ? 0 : timestamp); + input_files[nb_input_files - 1].nb_streams = ic->nb_streams; frame_rate = (AVRational){0, 0}; frame_pix_fmt = PIX_FMT_NONE; From dd8d808ba6d4539194ede465f5bc67daeae1f2de Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 21 Sep 2011 14:57:29 +0200 Subject: [PATCH 17/19] doc: library versions need to be bumped in version.h --- doc/developer.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/developer.texi b/doc/developer.texi index 25bfe5a7bc..800009e89b 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -281,7 +281,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 From ae2e89717b05482a40a881dc99d91076a330a058 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 21 Sep 2011 15:23:34 +0100 Subject: [PATCH 18/19] dct-test: factor out some common code and do whas was likely intended This fixes some nonsensical code by moving some should-be-shared code to separate functions and using these. Signed-off-by: Mans Rullgard --- libavcodec/dct-test.c | 130 ++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 75 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 962b370c2b..90707f6181 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -199,6 +199,56 @@ static inline void mmx_emms(void) #endif } +static void init_block(DCTELEM block[64], int test, int is_idct, AVLFG *prng) +{ + 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) % 512) - 256; + 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) % 512 - 256; + break; + case 2: + block[ 0] = av_lfg_get(prng) % 4096 - 2048; + 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) { void (*ref)(DCTELEM *block) = is_idct ? ff_ref_idct : ff_ref_fdct; @@ -219,47 +269,8 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) 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) % 512) - 256; - 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) % 512 - 256; - } - break; - case 2: - block1[0] = av_lfg_get(&prng) % 4096 - 2048; - 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); + permute(block, block1, dct->format); dct->func(block); mmx_emms(); @@ -316,45 +327,14 @@ static int dct_error(const struct algo *dct, int test, int is_idct, int speed) 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) % 512 - 256; - 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) % 512 - 256; - block1[1] = av_lfg_get(&prng) % 512 - 256; - block1[2] = av_lfg_get(&prng) % 512 - 256; - block1[3] = av_lfg_get(&prng) % 512 - 256; - 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); + 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; From 05fc9e40a4e4f808d457512420b887f458d216bc Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Tue, 20 Sep 2011 18:40:43 -0700 Subject: [PATCH 19/19] swfdec: Add support for sample_rate_code 0 (5512 Hz) --- libavformat/swfdec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 59977a94a6..502647f9a2 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) {