[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