[FFmpeg-devel] [RFC][PATCH 3/3] tta: Add support for encrypted streams
James Almer
jamrial at gmail.com
Sun Jan 27 07:52:15 CET 2013
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);
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) {
+ 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
More information about the ffmpeg-devel
mailing list