[FFmpeg-devel] [RFC][PATCH 3/3] tta: Add support for encrypted streams

Paul B Mahol onemda at gmail.com
Sun Jan 27 16:39:18 CET 2013


On 1/27/13, James Almer <jamrial at gmail.com> wrote:
> The code to decrypt data is added to the decoder, and
> the needed code to provide the decrypt key is added
> to the TTA demuxer.
>
> Any other container that supports TTA streams will
> need extra code to process the password and send it
> to the decoder using packet side data (main extradata
> is used for the TTA header).
>
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
>  libavcodec/tta.c  | 27 ++++++++++++++++++---------
>  libavformat/tta.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 66 insertions(+), 11 deletions(-)
>
> diff --git a/libavcodec/tta.c b/libavcodec/tta.c
> index fb793be..b012408 100644
> --- a/libavcodec/tta.c
> +++ b/libavcodec/tta.c
> @@ -44,7 +44,7 @@ typedef struct TTAFilter {
>      int32_t qm[MAX_ORDER];
>      int32_t dx[MAX_ORDER];
>      int32_t dl[MAX_ORDER];
> -} TTAFilter;
> +DECLARE_ALIGNED(16, }, TTAFilter);

This looks strange to me.

>
>  typedef struct TTARice {
>      uint32_t k0, k1, sum0, sum1;
> @@ -93,8 +93,13 @@ static const int32_t ttafilter_configs[4] = {
>      12
>  };
>
> -static void ttafilter_init(TTAFilter *c, int32_t shift) {
> +static void ttafilter_init(TTAFilter *c, int32_t shift, const uint8_t
> *pass) {
>      memset(c, 0, sizeof(TTAFilter));
> +    if (pass) {
> +        int i;
> +        for(i = 0; i < 8; i++)
> +            c->qm[i] = sign_extend(pass[i], 8);
> +    }
>      c->shift = shift;
>     c->round = shift_1[shift-1];
>  //    c->round = 1 << (shift - 1);
> @@ -200,10 +205,6 @@ static av_cold int tta_decode_init(AVCodecContext *
> avctx)
>              av_log(avctx, AV_LOG_ERROR, "Invalid format\n");
>              return AVERROR_INVALIDDATA;
>          }
> -        if (s->format == FORMAT_ENCRYPTED) {
> -            av_log_missing_feature(avctx, "Encrypted TTA", 0);
> -            return AVERROR_PATCHWELCOME;
> -        }
>          avctx->channels = s->channels = get_bits(&s->gb, 16);
>          if (s->channels > 1 && s->channels < 9)
>              avctx->channel_layout = tta_channel_layouts[s->channels-2];
> @@ -293,8 +294,8 @@ static av_cold int tta_decode_init(AVCodecContext *
> avctx)
>  static int tta_decode_frame(AVCodecContext *avctx, void *data,
>                              int *got_frame_ptr, AVPacket *avpkt)
>  {
> -    const uint8_t *buf = avpkt->data;
> -    int buf_size = avpkt->size;
> +    const uint8_t *buf = avpkt->data, *sd_data = NULL;
> +    int buf_size = avpkt->size, sd_size;
>      TTAContext *s = avctx->priv_data;
>      int i, ret;
>      int cur_chan = 0, framelen = s->frame_length;
> @@ -318,10 +319,18 @@ static int tta_decode_frame(AVCodecContext *avctx,
> void *data,
>      if (s->bps == 3)
>          s->decode_buffer = (int32_t *)s->frame.data[0];
>
> +    if (s->format == FORMAT_ENCRYPTED) {
> +        sd_data = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA,
> &sd_size);
> +        if (!sd_data || sd_size != 8) {
> +            av_log(avctx, AV_LOG_ERROR, "Encrypted frame with no decryption
> info detected");
> +            return AVERROR_INVALIDDATA;
> +        }
> +    }
> +
>      // init per channel states
>      for (i = 0; i < s->channels; i++) {
>          s->ch_ctx[i].predictor = 0;
> -        ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1]);
> +        ttafilter_init(&s->ch_ctx[i].filter, ttafilter_configs[s->bps-1],
> sd_data);
>          rice_init(&s->ch_ctx[i].rice, 10, 10);
>      }
>
> diff --git a/libavformat/tta.c b/libavformat/tta.c
> index 445389e..c17b9e5 100644
> --- a/libavformat/tta.c
> +++ b/libavformat/tta.c
> @@ -23,12 +23,19 @@
>  #include "avformat.h"
>  #include "internal.h"
>  #include "id3v1.h"
> +#include "libavutil/crc.h"
>  #include "libavutil/dict.h"
> +#include "libavutil/intreadwrite.h"
> +#include "libavutil/opt.h"
>
>  typedef struct {
> +    const AVClass *tta_demuxer_class;
>      int totalframes, currentframe;
>      int frame_size;
>      int last_frame_size;
> +    int format;
> +    uint8_t crc_pass[8];
> +    uint8_t *pass;
>  } TTAContext;
>
>  static int tta_probe(AVProbeData *p)
> @@ -44,7 +51,7 @@ static int tta_read_header(AVFormatContext *s)
>  {
>      TTAContext *c = s->priv_data;
>      AVStream *st;
> -    int i, channels, bps, samplerate;
> +    int i, channels, bps, samplerate, format;
>      uint64_t framepos, start_offset;
>      uint32_t datalen;
>
> @@ -55,7 +62,22 @@ static int tta_read_header(AVFormatContext *s)
>      if (avio_rl32(s->pb) != AV_RL32("TTA1"))
>          return -1; // not tta file
>
> -    avio_skip(s->pb, 2); // FIXME: flags
> +    format = avio_rl16(s->pb);
> +    if (format == 2) {
> +        uint64_t crc;
> +
> +        if (!c->pass) {
> +            av_log(s, AV_LOG_ERROR, "Missing password for encypted stream.
> Please use the -password option\n");
> +            return AVERROR(EINVAL);
> +        }
> +
> +        crc = av_crc2(av_crc_get_table(AV_CRC_64_ECMA), -1, c->pass,
> strlen(c->pass)) ^ UINT64_MAX;
> +        AV_WB64(c->crc_pass, crc);
> +    } else if (format > 2){
> +        av_log(s, AV_LOG_ERROR, "Invalid format\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
>      channels = avio_rl16(s->pb);
>      bps = avio_rl16(s->pb);
>      samplerate = avio_rl32(s->pb);
> @@ -78,6 +100,7 @@ static int tta_read_header(AVFormatContext *s)
>          c->last_frame_size = c->frame_size;
>      c->totalframes = datalen / c->frame_size + (c->last_frame_size <
> c->frame_size);
>      c->currentframe = 0;
> +    c->format = format;
>
>      if(c->totalframes >= UINT_MAX/sizeof(uint32_t) || c->totalframes <=
> 0){
>          av_log(s, AV_LOG_ERROR, "totalframes %d invalid\n",
> c->totalframes);
> @@ -141,6 +164,14 @@ static int tta_read_packet(AVFormatContext *s, AVPacket
> *pkt)
>      pkt->dts = st->index_entries[c->currentframe++].timestamp;
>      pkt->duration = c->currentframe == c->totalframes ? c->last_frame_size
> :
>                                                          c->frame_size;
> +    if (c->format == 2) {

2 could be replaced with something more friendly....

> +        uint8_t *crc;
> +
> +        if ((crc = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
> 8)) == NULL)
> +            return AVERROR(ENOMEM);
> +        memcpy(crc, c->crc_pass, 8);
> +    }
> +
>      return ret;
>  }
>
> @@ -159,6 +190,20 @@ static int tta_read_seek(AVFormatContext *s, int
> stream_index, int64_t timestamp
>      return 0;
>  }
>
> +#define OFFSET(x) offsetof(TTAContext, x)
> +#define DEC AV_OPT_FLAG_DECODING_PARAM
> +static const AVOption options[] = {
> +    { "password", "Set decoding password", OFFSET(pass),
> AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, DEC },
> +    { NULL },
> +};
> +
> +static const AVClass tta_demuxer_class = {
> +    .class_name = "TTA demuxer",
> +    .item_name  = av_default_item_name,
> +    .option     = options,
> +    .version    = LIBAVUTIL_VERSION_INT,
> +};
> +
>  AVInputFormat ff_tta_demuxer = {
>      .name           = "tta",
>      .long_name      = NULL_IF_CONFIG_SMALL("TTA (True Audio)"),
> @@ -168,4 +213,5 @@ AVInputFormat ff_tta_demuxer = {
>      .read_packet    = tta_read_packet,
>      .read_seek      = tta_read_seek,
>      .extensions     = "tta",
> +    .priv_class     = &tta_demuxer_class,
>  };
> --
> 1.7.12.4
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>


More information about the ffmpeg-devel mailing list