diff --git a/packages/multimedia/ffmpeg/patches/ffmpeg-0.10.5-912-Vividas-support-for-IPLEX-for-current-ffmpeg.patch b/packages/multimedia/ffmpeg/patches/ffmpeg-0.10.5-912-Vividas-support-for-IPLEX-for-current-ffmpeg.patch new file mode 100644 index 0000000000..384115fe2f --- /dev/null +++ b/packages/multimedia/ffmpeg/patches/ffmpeg-0.10.5-912-Vividas-support-for-IPLEX-for-current-ffmpeg.patch @@ -0,0 +1,1569 @@ +From ec459ccb9a7eadee41afd4da2b71a52e18dceae6 Mon Sep 17 00:00:00 2001 +From: Tomasz Jezierski +Date: Thu, 6 Sep 2012 20:14:27 +0200 +Subject: [PATCH] Vividas support for IPLEX for current ffmpeg +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ported to current ffmpeg version +Copyright (c) 2010 Andrzej Szombierski +based on vivparse Copyright (c) 2007 Måns Rullgård +--- + libavformat/Makefile | 1 + + libavformat/allformats.c | 1 + + libavformat/vividas.c | 740 ++++++++++++++++++++++++ + patches/0110-vividas-support.patch | 770 +++++++++++++++++++++++++ + 4 files changed, 1512 insertions(+) + create mode 100644 libavformat/vividas.c + create mode 100644 patches/0110-vividas-support.patch + +diff --git a/libavformat/Makefile b/libavformat/Makefile +index bd2b17b..6642498 100644 +--- a/libavformat/Makefile ++++ b/libavformat/Makefile +@@ -315,6 +315,7 @@ OBJS-$(CONFIG_TXD_DEMUXER) += txd.o + OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o + OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o + OBJS-$(CONFIG_VC1T_MUXER) += vc1testenc.o ++OBJS-$(CONFIG_VIVIDAS_DEMUXER) += vividas.o + OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o + OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o + OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o +diff --git a/libavformat/allformats.c b/lib/ffmpeg/libavformat/allformats.c +index 134839f..0af5ba9 100644 +--- a/libavformat/allformats.c ++++ b/libavformat/allformats.c +@@ -232,6 +232,7 @@ void av_register_all(void) + REGISTER_DEMUXER (TTY, tty); + REGISTER_DEMUXER (VC1, vc1); + REGISTER_MUXDEMUX (VC1T, vc1t); ++ REGISTER_DEMUXER (VIVIDAS, vividas); + REGISTER_DEMUXER (VMD, vmd); + REGISTER_MUXDEMUX (VOC, voc); + REGISTER_DEMUXER (VQF, vqf); +diff --git a/libavformat/vividas.c b/libavformat/vividas.c +new file mode 100644 +index 0000000..2d3ba27 +--- /dev/null ++++ b/libavformat/vividas.c +@@ -0,0 +1,740 @@ ++/* ++ * Vividas VIV format Demuxer ++ * Copyright (c) 2010 Andrzej Szombierski ++ * based on vivparse Copyright (c) 2007 Måns Rullgård ++ * ++ * This file is part of FFmpeg. ++ * ++ * FFmpeg is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * FFmpeg is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with FFmpeg; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++/** ++ * @file ++ * @brief Vividas VIV (.viv) file demuxer ++ * @author Andrzej Szombierski [qq at kuku eu org] (2010-07) ++ * @sa http://wiki.multimedia.cx/index.php?title=Vividas_VIV ++ */ ++ ++#define AV_PKT_FLAG_KEY 0x0001 ++ ++#include "libavutil/intreadwrite.h" ++#include "avio_internal.h" ++#include "avformat.h" ++ ++#define MAX_AUDIO_SUBPACKETS 100 ++#define CODEC_TYPE_VIDEO AVMEDIA_TYPE_VIDEO ++#define CODEC_TYPE_AUDIO AVMEDIA_TYPE_AUDIO ++ ++typedef struct VIV_SB_block { ++ int size, n_packets; ++ int64_t byte_offset; ++ int packet_offset; ++} VIV_SB_block; ++ ++typedef struct VIV_SB_entry { ++ int size, flag; ++} VIV_SB_entry; ++ ++typedef struct VIV_AudioSubpacket { ++ int start, pcm_bytes; ++} VIV_AudioSubpacket; ++ ++typedef struct VIV_DemuxContext ++{ ++ int n_sb_blocks; ++ VIV_SB_block *sb_blocks; ++ ++ uint32_t sb_key; ++ int64_t sb_offset; ++ ++ int current_sb, current_sb_entry; ++ uint8_t *sb_buf; ++ AVIOContext *sb_pb; ++ int n_sb_entries; ++ VIV_SB_entry *sb_entries; ++ ++ int n_audio_subpackets; ++ int current_audio_subpacket; ++ ++ int audio_sample; ++ ++ VIV_AudioSubpacket audio_subpackets[MAX_AUDIO_SUBPACKETS]; ++} VIV_DemuxContext; ++ ++static int viv_probe(AVProbeData *p) ++{ ++ if(strncmp((char*)p->buf, "vividas03", 9)) ++ return 0; ++ ++ return AVPROBE_SCORE_MAX; ++} ++ ++const unsigned short keybits[32] = { ++ 163, 416, 893, 82, 223, 572, 1137, 430, ++ 659, 1104, 13, 626, 695, 972, 1465, 686, ++ 843, 1216, 317, 1122, 1383, 92, 513, 1158, ++ 1243, 48, 573, 1306, 1495, 396, 1009, 350, ++}; ++ ++static uint32_t decode_key(uint8_t *buf) ++{ ++ uint32_t key = 0; ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ unsigned p = keybits[i]; ++ key |= !!(buf[p>>3] & (1<<(p&7))) << i; ++ } ++ ++ return key; ++} ++ ++static void put_v(uint8_t *p, int v) ++{ ++ if(v>>28) ++ *p++ = ((v>>28)&0x7f)|0x80; ++ if(v>>21) ++ *p++ = ((v>>21)&0x7f)|0x80; ++ if(v>>14) ++ *p++ = ((v>>14)&0x7f)|0x80; ++ if(v>>7) ++ *p++ = ((v>>7)&0x7f)|0x80; ++ *p++ = v&0x7f; ++} ++ ++static unsigned int recover_key(unsigned char sample[4], int expected_size) ++{ ++ unsigned char plaintext[8] = { 'S', 'B' }; ++ put_v(plaintext+2, expected_size); ++ ++ return (sample[0]^plaintext[0])| ++ ((sample[1]^plaintext[1])<<8)| ++ ((sample[2]^plaintext[2])<<16)| ++ ((sample[3]^plaintext[3])<<24); ++} ++ ++static void xor_block(void *p1, void *p2, int size, int key, int *key_ptr) ++{ ++ int *d1 = p1; ++ int *d2 = p2; ++ int k = *key_ptr; ++ ++ size >>= 2; ++ ++ while (size--) { ++ *d2 = *d1 ^ k; ++ k += key; ++ d1++; ++ d2++; ++ } ++ ++ *key_ptr = k; ++} ++ ++static void decode_block(uint8_t *src, uint8_t *dest, int size, ++ uint32_t key, uint32_t *key_ptr, ++ int align) ++{ ++ int s = size; ++ char tmp[4]; ++ int a2; ++ ++ if (!size) ++ return; ++ ++ align &= 3; ++ a2 = (4 - align) & 3; ++ ++ if (align) { ++ uint32_t tmpkey = *key_ptr - key; ++ memcpy(tmp + align, src, a2); ++ xor_block(tmp, tmp, 4, key, &tmpkey); ++ memcpy(dest, tmp + align, a2); ++ s -= a2; ++ } ++ ++ if (s >= 4) { ++ if (!align) ++ align = 4; ++ xor_block(src + a2, dest + a2, s & ~3, ++ key, key_ptr); ++ s &= 3; ++ } ++ ++ if (s) { ++ size -= s; ++ memcpy(tmp, src + size, s); ++ xor_block(&tmp, &tmp, 4, key, key_ptr); ++ memcpy(dest + size, tmp, s); ++ } ++} ++ ++static uint32_t get_v(uint8_t *p) ++{ ++ uint32_t v = 0; ++ ++ do { ++ v <<= 7; ++ v += *p & 0x7f; ++ } while (*p++ & 0x80); ++ ++ return v; ++} ++ ++static uint8_t *read_vblock(AVIOContext *src, uint32_t *size, uint32_t key, uint32_t *k2, int align) ++{ ++ uint8_t tmp[4]; ++ uint8_t *buf; ++ unsigned n; ++ ++ if(avio_read(src, tmp, 4) != 4) ++ return NULL; ++ ++ decode_block(tmp, tmp, 4, key, k2, align); ++ ++ n = get_v(tmp); ++ ++ buf = av_malloc(n); ++ if (!buf) ++ return NULL; ++ ++ *size = n; ++ n -= 4; ++ ++ memcpy(buf, tmp, 4); ++ ++ if (avio_read(src, buf + 4, n) == n) { ++ decode_block(buf + 4, buf + 4, n, key, k2, align + 4); ++ } else { ++ av_free(buf); ++ buf = NULL; ++ } ++ ++ return buf; ++} ++ ++static uint8_t *read_sb_block(AVIOContext *src, unsigned *size, uint32_t *key, int expected_size) ++{ ++ uint8_t *buf; ++ uint8_t ibuf[8], sbuf[8]; ++ uint32_t k2; ++ int n; ++ ++ if (avio_read(src, ibuf, 8) < 8) ++ return NULL; ++ ++ k2 = *key; ++ decode_block(ibuf, sbuf, 8, *key, &k2, 0); ++ ++ n = get_v(sbuf+2); ++ ++ if (sbuf[0] != 'S' || sbuf[1] != 'B' || (expected_size>0 && n != expected_size)) { ++ uint32_t tmpkey = recover_key(ibuf, expected_size); ++ k2 = tmpkey; ++ decode_block(ibuf, sbuf, 8, tmpkey, &k2, 0); ++ n = get_v(sbuf+2); ++ if(sbuf[0] != 'S' || sbuf[1] != 'B' || expected_size != n) ++ return NULL; ++ *key = tmpkey; ++ } ++ ++ buf = av_malloc(n); ++ if (!buf) ++ return NULL; ++ ++ memcpy(buf, sbuf, 8); ++ ++ *size = n; ++ n -= 8; ++ ++ if (avio_read(src, buf+8, n) < n) { ++ av_free(buf); ++ return NULL; ++ } ++ ++ decode_block(buf + 8, buf + 8, n, *key, &k2, 0); ++ ++ return buf; ++} ++ ++static void track_header(VIV_DemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) ++{ ++ int i,j; ++ int64_t off; ++ int val_1; ++ int num_video, num_audio; ++ AVIOContext *pb=0; ++ ++ pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); ++ //ff_get_v(pb); // track_header_len ++ ffio_read_varlen(pb); // track_header_len ++ avio_r8(pb); // '1' ++ ++ //val_1 = ff_get_v(pb); ++ val_1 = ffio_read_varlen(pb); ++ ++ for(i=0;icodec; ++ ++ st->id = i; ++ ++ vcodec->codec_type = CODEC_TYPE_VIDEO; ++ vcodec->codec_id = CODEC_ID_VP6; ++ ++ off = avio_tell(pb); ++ //off += ff_get_v(pb); ++ off += ffio_read_varlen(pb); ++ avio_r8(pb); // '3' ++ avio_r8(pb); // val_7 ++ st->time_base.num = avio_rl32(pb); // frame_time ++ st->time_base.den = avio_rl32(pb); // time_base ++ st->nb_frames = avio_rl32(pb); // n frames ++ vcodec->width = avio_rl16(pb); // width ++ vcodec->height = avio_rl16(pb); // height ++ avio_r8(pb); // val_8 ++ avio_rl32(pb); // val_9 ++ ++ vcodec->flags |= CODEC_FLAG_GLOBAL_HEADER; // ? ++ ++ avio_seek(pb, off, SEEK_SET); ++ } ++ ++ off = avio_tell(pb); ++ //off += ff_get_v(pb); // val_10 ++ off += ffio_read_varlen(pb); // val_10 ++ avio_r8(pb); // '4' ++ num_audio = avio_r8(pb); ++ avio_seek(pb, off, SEEK_SET); ++ ++ if(num_audio != 1) ++ av_log(s, AV_LOG_WARNING, "viv: number of audio tracks %d is not 1\n", num_audio); ++ ++ for(i=0;icodec; ++ ++ st->id = num_video + i; ++ ++ acodec->codec_type = CODEC_TYPE_AUDIO; ++ acodec->codec_id = CODEC_ID_VORBIS; ++ acodec->flags |= CODEC_FLAG_GLOBAL_HEADER; // ? ++ ++ off = avio_tell(pb); ++ //off += ff_get_v(pb); // length ++ off += ffio_read_varlen(pb); // length ++ avio_r8(pb); // '5' ++ avio_r8(pb); //codec_id ++ avio_rl16(pb); //codec_subid ++ acodec->channels = avio_rl16(pb); // channels ++ acodec->sample_rate = avio_rl32(pb); // sample_rate ++ avio_seek(pb, 10, SEEK_CUR); // data_1 ++ q = avio_r8(pb); ++ avio_seek(pb, q, SEEK_CUR); // data_2 ++ avio_r8(pb); // zeropad ++ ++ if(avio_tell(pb) < off) { ++ int num_data; ++ int xd_size = 0; ++ int data_len[256]; ++ uint8_t * p; ++ int offset = 1; ++ //ff_get_v(pb); // val_13 ++ ffio_read_varlen(pb); // val_13 ++ avio_r8(pb); // '19' ++ //ff_get_v(pb); // len_3 ++ ffio_read_varlen(pb); // len_3 ++ num_data = avio_r8(pb); ++ for(j=0;jextradata_size = 64 + xd_size + xd_size / 255; ++ acodec->extradata = (uint8_t*)av_mallocz(acodec->extradata_size); ++ ++ p = acodec->extradata; ++ p[0] = 2; ++ ++ for(j=0;jextradata_size = offset; ++ } ++ } ++ ++ av_free(pb); ++} ++ ++static void track_index(VIV_DemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) ++{ ++ int i; ++ int64_t off; ++ int poff; ++ int maxnp=0; ++ AVIOContext *pb=0; ++ ++ pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); ++ //ff_get_v(pb); // track_index_len ++ ffio_read_varlen(pb); // track_index_len ++ avio_r8(pb); // 'c' ++ //viv->n_sb_blocks = ff_get_v(pb); ++ viv->n_sb_blocks = ffio_read_varlen(pb); ++ viv->sb_blocks = av_mallocz(sizeof(VIV_SB_block) * viv->n_sb_blocks); ++ if(!viv->sb_blocks) { ++ viv->n_sb_blocks = 0; ++ av_free(pb); ++ return; ++ } ++ ++ off = 0; ++ poff = 0; ++ ++ for(i=0;in_sb_blocks;i++) { ++ viv->sb_blocks[i].byte_offset = off; ++ viv->sb_blocks[i].packet_offset = poff; ++ ++ //viv->sb_blocks[i].size = ff_get_v(pb); ++ //viv->sb_blocks[i].n_packets = ff_get_v(pb); ++ viv->sb_blocks[i].size = ffio_read_varlen(pb); ++ viv->sb_blocks[i].n_packets = ffio_read_varlen(pb); ++ ++ off += viv->sb_blocks[i].size; ++ poff += viv->sb_blocks[i].n_packets; ++ ++ ++ if(maxnp < viv->sb_blocks[i].n_packets) ++ maxnp = viv->sb_blocks[i].n_packets; ++ } ++ ++ viv->sb_entries = av_mallocz(maxnp * sizeof(VIV_SB_entry)); ++ av_free(pb); ++} ++ ++static void load_sb_block(AVFormatContext *s, VIV_DemuxContext *viv, int expected_size) ++{ ++ uint32_t size=0; ++ int i; ++ AVIOContext *pb = 0; ++ if(viv->sb_pb) { ++ av_free(viv->sb_pb); ++ viv->sb_pb = NULL; ++ } ++ ++ if(viv->sb_buf) ++ av_free(viv->sb_buf); ++ ++ viv->sb_buf = read_sb_block(s->pb, &size, &viv->sb_key, expected_size); ++ if(!viv->sb_buf) { ++ return; ++ } ++ ++ pb = avio_alloc_context(viv->sb_buf, size, 0, NULL, NULL, NULL, NULL); ++ viv->sb_pb = pb; ++ ++ avio_r8(pb); // 'S' ++ avio_r8(pb); // 'B' ++ //ff_get_v(pb); // size ++ ffio_read_varlen(pb); // size ++ avio_r8(pb); // junk ++ //ff_get_v(pb); // first packet ++ ffio_read_varlen(pb); // first packet ++ ++ viv->n_sb_entries = viv->sb_blocks[viv->current_sb].n_packets; ++ ++ for(i=0;in_sb_entries;i++) { ++ //viv->sb_entries[i].size = ff_get_v(pb); ++ viv->sb_entries[i].size = ffio_read_varlen(pb); ++ viv->sb_entries[i].flag = avio_r8(pb); ++ } ++ ++ //ff_get_v(pb); // 0 ++ ffio_read_varlen(pb); // 0 ++ avio_r8(pb); // 0 ++ ++ viv->current_sb_entry = 0; ++} ++ ++static int viv_read_header(AVFormatContext *s, ++ AVFormatParameters *ap) ++{ ++ VIV_DemuxContext *viv = s->priv_data; ++ AVIOContext *pb = s->pb; ++ int64_t header_end; ++ int num_tracks; ++ uint32_t key, k2; ++ uint32_t v; ++ uint8_t keybuffer[187]; ++ uint32_t b22_size = 0; ++ uint32_t b22_key = 0; ++ uint8_t *buf = 0; ++ ++ // string "vividas03" ++ avio_seek(pb, 9, SEEK_CUR); ++ ++ header_end = avio_tell(pb); ++ ++ // v: header size ++ //header_end += ff_get_v(pb); ++ header_end += ffio_read_varlen(pb); ++ ++ // u8: n tracks ++ num_tracks = avio_r8(pb); ++ ++ if(num_tracks != 1) { ++ av_log(s, AV_LOG_ERROR, "number of tracks %d is not 1\n", num_tracks); ++ return AVERROR(EINVAL); ++ } ++ ++ v = avio_r8(pb); ++ avio_seek(pb, v, SEEK_CUR); ++ ++ avio_read(pb, keybuffer, 187); ++ key = decode_key(keybuffer); ++ viv->sb_key = key; ++ ++ avio_rl32(pb); // track_header_len ++ ++ for(;;) { ++ int64_t here = avio_tell(pb); ++ int block_len, block_type; ++ ++ if(here >= header_end) ++ break; ++ ++ //block_len = ff_get_v(pb); ++ block_len = ffio_read_varlen(pb); ++ block_type = avio_r8(pb); ++ ++ if(block_type == 22) { ++ avio_read(pb, keybuffer, 187); ++ b22_key = decode_key(keybuffer); ++ b22_size = avio_rl32(pb); ++ } ++ ++ avio_seek(pb, here + block_len, SEEK_SET); ++ } ++ ++ if(b22_size) { ++ k2 = b22_key; ++ buf = read_vblock(pb, &v, b22_key, &k2, 0); ++ if(!buf) ++ return AVERROR(EIO); ++ ++ av_free(buf); ++ } ++ ++ k2 = key; ++ buf = read_vblock(pb, &v, key, &k2, 0); ++ if(!buf) ++ return AVERROR(EIO); ++ track_header(viv, s, buf, v); ++ av_free(buf); ++ ++ buf = read_vblock(pb, &v, key, &k2, v); ++ if(!buf) ++ return AVERROR(EIO); ++ track_index(viv, s, buf, v); ++ av_free(buf); ++ ++ viv->sb_offset = avio_tell(pb); ++ if(viv->n_sb_blocks > 0) { ++ viv->current_sb = 0; ++ load_sb_block(s, viv, viv->sb_blocks[0].size); ++ } else { ++ viv->current_sb = -1; ++ } ++ ++ return 0; ++} ++ ++static int viv_read_packet(AVFormatContext *s, ++ AVPacket *pkt) ++{ ++ VIV_DemuxContext *viv = s->priv_data; ++ AVIOContext *pb; ++ int64_t off; ++ ++ if(viv->current_audio_subpacket < viv->n_audio_subpackets) { ++ // audio packets ++ AVStream *astream; ++ int size = viv->audio_subpackets[viv->current_audio_subpacket+1].start - viv->audio_subpackets[viv->current_audio_subpacket].start; ++ pb = viv->sb_pb; ++ av_get_packet(pb, pkt, size); ++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; ++ ++ pkt->stream_index = 1; ++ astream = s->streams[pkt->stream_index]; ++ ++ pkt->pts = viv->audio_sample * (long long)astream->time_base.den / (long long)astream->time_base.num / (long long)astream->codec->sample_rate; ++ viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / astream->codec->channels; ++ pkt->flags |= AV_PKT_FLAG_KEY; ++ viv->current_audio_subpacket++; ++ return 0; ++ } ++ ++ if(viv->current_sb_entry >= viv->n_sb_entries) { ++ if(viv->current_sb+1 >= viv->n_sb_blocks) ++ return AVERROR(EIO); ++ viv->current_sb++; ++ ++ load_sb_block(s, viv, 0); ++ viv->current_sb_entry = 0; ++ } ++ ++ pb = viv->sb_pb; ++ off = avio_tell(pb); ++ off += viv->sb_entries[viv->current_sb_entry].size; ++ ++ if(viv->sb_entries[viv->current_sb_entry].flag == 0) { ++ // A/V packet ++ int i; ++ //int v_size = ff_get_v(pb); ++ int v_size = ffio_read_varlen(pb); ++ ///*int a_size = */ff_get_v(pb); ++ /*int a_size = */ffio_read_varlen(pb); ++ av_get_packet(pb, pkt, v_size); ++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; ++ ++ pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; ++ pkt->flags |= (pkt->data[0]&0x80)?0:AV_PKT_FLAG_KEY; ++ pkt->stream_index = 0; ++ ++ for(i=0;i 0 && start == 0) ++ break; ++ ++ viv->n_audio_subpackets = i+1; ++ viv->audio_subpackets[i].start = start; ++ viv->audio_subpackets[i].pcm_bytes = pcm_bytes; ++ } ++ viv->audio_subpackets[viv->n_audio_subpackets].start = (int)(off - avio_tell(pb)); ++ viv->current_audio_subpacket = 0; ++ //viv->n_audio_subpackets = 0; ++ //avio_seek(pb, off, SEEK_SET); ++ ++ } else { ++ // V packet ++ //int v_size = ff_get_v(pb); ++ int v_size = ffio_read_varlen(pb); ++ av_get_packet(pb, pkt, v_size); ++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; ++ pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; ++ pkt->flags |= (pkt->data[0]&0x80)?0:AV_PKT_FLAG_KEY; ++ pkt->stream_index = 0; ++ } ++ ++ viv->current_sb_entry++; ++ ++// avio_seek(pb, off, SEEK_SET); ++ ++ return 0; ++} ++ ++static int viv_read_close(AVFormatContext *s) ++{ ++ VIV_DemuxContext *viv = s->priv_data; ++ if(viv->sb_pb) ++ av_free(viv->sb_pb); ++ ++ if(viv->sb_buf) ++ av_free(viv->sb_buf); ++ ++ if(viv->sb_blocks) ++ av_free(viv->sb_blocks); ++ ++ if(viv->sb_entries) ++ av_free(viv->sb_entries); ++ ++ return 0; ++} ++ ++static int viv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) ++{ ++ VIV_DemuxContext *viv = s->priv_data; ++ int frame = 0; ++ int i; ++ ++ if(stream_index == 0) ++ frame = (int)timestamp; ++ else ++ frame = (int)timestamp * s->streams[stream_index]->time_base.den * s->streams[0]->time_base.num / s->streams[stream_index]->time_base.num / s->streams[0]->time_base.den; ++ ++ for(i=0;in_sb_blocks;i++) { ++ if(frame >= viv->sb_blocks[i].packet_offset && frame < viv->sb_blocks[i].packet_offset + viv->sb_blocks[i].n_packets) { ++ // flush audio packet queue ++ viv->current_audio_subpacket = 0; ++ viv->n_audio_subpackets = 0; ++ viv->current_sb = i; ++ // seek to ith sb block ++ avio_seek(s->pb, viv->sb_offset + viv->sb_blocks[i].byte_offset, SEEK_SET); ++ // load the block ++ load_sb_block(s, viv, 0); ++ // most problematic part: guess audio offset ++ viv->audio_sample = (int64_t)viv->sb_blocks[i].packet_offset * (int64_t)s->streams[1]->codec->sample_rate * s->streams[0]->time_base.num / s->streams[0]->time_base.den; ++ // hand-tuned 1.3s a/v offset ++ viv->audio_sample += 1300 * s->streams[1]->codec->sample_rate / 1000; ++ viv->current_sb_entry = 0; ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++AVInputFormat ff_vividas_demuxer = { ++ "vividas", ++ "Vividas VIV format", ++ sizeof(VIV_DemuxContext), ++ viv_probe, ++ viv_read_header, ++ viv_read_packet, ++ viv_read_close, ++ viv_read_seek ++}; ++ +diff --git a/patches/0110-vividas-support.patch b/patches/0110-vividas-support.patch +new file mode 100644 +index 0000000..713a0a5 +--- /dev/null ++++ b/patches/0110-vividas-support.patch +@@ -0,0 +1,770 @@ ++diff --git a/lib/ffmpeg/libavformat/Makefile b/lib/ffmpeg/libavformat/Makefile ++index bd2b17b..6642498 100644 ++--- a/lib/ffmpeg/libavformat/Makefile +++++ b/lib/ffmpeg/libavformat/Makefile ++@@ -315,6 +315,7 @@ OBJS-$(CONFIG_TXD_DEMUXER) += txd.o ++ OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o ++ OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o ++ OBJS-$(CONFIG_VC1T_MUXER) += vc1testenc.o +++OBJS-$(CONFIG_VIVIDAS_DEMUXER) += vividas.o ++ OBJS-$(CONFIG_VMD_DEMUXER) += sierravmd.o ++ OBJS-$(CONFIG_VOC_DEMUXER) += vocdec.o voc.o ++ OBJS-$(CONFIG_VOC_MUXER) += vocenc.o voc.o ++diff --git a/lib/ffmpeg/libavformat/allformats.c b/lib/ffmpeg/libavformat/allformats.c ++index 134839f..0af5ba9 100644 ++--- a/lib/ffmpeg/libavformat/allformats.c +++++ b/lib/ffmpeg/libavformat/allformats.c ++@@ -232,6 +232,7 @@ void av_register_all(void) ++ REGISTER_DEMUXER (TTY, tty); ++ REGISTER_DEMUXER (VC1, vc1); ++ REGISTER_MUXDEMUX (VC1T, vc1t); +++ REGISTER_DEMUXER (VIVIDAS, vividas); ++ REGISTER_DEMUXER (VMD, vmd); ++ REGISTER_MUXDEMUX (VOC, voc); ++ REGISTER_DEMUXER (VQF, vqf); ++diff --git a/lib/ffmpeg/libavformat/vividas.c b/lib/ffmpeg/libavformat/vividas.c ++new file mode 100644 ++index 0000000..2d3ba27 ++--- /dev/null +++++ b/lib/ffmpeg/libavformat/vividas.c ++@@ -0,0 +1,740 @@ +++/* +++ * Vividas VIV format Demuxer +++ * Copyright (c) 2010 Andrzej Szombierski +++ * based on vivparse Copyright (c) 2007 Måns Rullgård +++ * +++ * This file is part of FFmpeg. +++ * +++ * FFmpeg is free software; you can redistribute it and/or +++ * modify it under the terms of the GNU Lesser General Public +++ * License as published by the Free Software Foundation; either +++ * version 2.1 of the License, or (at your option) any later version. +++ * +++ * FFmpeg is distributed in the hope that it will be useful, +++ * but WITHOUT ANY WARRANTY; without even the implied warranty of +++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +++ * Lesser General Public License for more details. +++ * +++ * You should have received a copy of the GNU Lesser General Public +++ * License along with FFmpeg; if not, write to the Free Software +++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +++ */ +++ +++/** +++ * @file +++ * @brief Vividas VIV (.viv) file demuxer +++ * @author Andrzej Szombierski [qq at kuku eu org] (2010-07) +++ * @sa http://wiki.multimedia.cx/index.php?title=Vividas_VIV +++ */ +++ +++#define AV_PKT_FLAG_KEY 0x0001 +++ +++#include "libavutil/intreadwrite.h" +++#include "avio_internal.h" +++#include "avformat.h" +++ +++#define MAX_AUDIO_SUBPACKETS 100 +++#define CODEC_TYPE_VIDEO AVMEDIA_TYPE_VIDEO +++#define CODEC_TYPE_AUDIO AVMEDIA_TYPE_AUDIO +++ +++typedef struct VIV_SB_block { +++ int size, n_packets; +++ int64_t byte_offset; +++ int packet_offset; +++} VIV_SB_block; +++ +++typedef struct VIV_SB_entry { +++ int size, flag; +++} VIV_SB_entry; +++ +++typedef struct VIV_AudioSubpacket { +++ int start, pcm_bytes; +++} VIV_AudioSubpacket; +++ +++typedef struct VIV_DemuxContext +++{ +++ int n_sb_blocks; +++ VIV_SB_block *sb_blocks; +++ +++ uint32_t sb_key; +++ int64_t sb_offset; +++ +++ int current_sb, current_sb_entry; +++ uint8_t *sb_buf; +++ AVIOContext *sb_pb; +++ int n_sb_entries; +++ VIV_SB_entry *sb_entries; +++ +++ int n_audio_subpackets; +++ int current_audio_subpacket; +++ +++ int audio_sample; +++ +++ VIV_AudioSubpacket audio_subpackets[MAX_AUDIO_SUBPACKETS]; +++} VIV_DemuxContext; +++ +++static int viv_probe(AVProbeData *p) +++{ +++ if(strncmp((char*)p->buf, "vividas03", 9)) +++ return 0; +++ +++ return AVPROBE_SCORE_MAX; +++} +++ +++const unsigned short keybits[32] = { +++ 163, 416, 893, 82, 223, 572, 1137, 430, +++ 659, 1104, 13, 626, 695, 972, 1465, 686, +++ 843, 1216, 317, 1122, 1383, 92, 513, 1158, +++ 1243, 48, 573, 1306, 1495, 396, 1009, 350, +++}; +++ +++static uint32_t decode_key(uint8_t *buf) +++{ +++ uint32_t key = 0; +++ int i; +++ +++ for (i = 0; i < 32; i++) { +++ unsigned p = keybits[i]; +++ key |= !!(buf[p>>3] & (1<<(p&7))) << i; +++ } +++ +++ return key; +++} +++ +++static void put_v(uint8_t *p, int v) +++{ +++ if(v>>28) +++ *p++ = ((v>>28)&0x7f)|0x80; +++ if(v>>21) +++ *p++ = ((v>>21)&0x7f)|0x80; +++ if(v>>14) +++ *p++ = ((v>>14)&0x7f)|0x80; +++ if(v>>7) +++ *p++ = ((v>>7)&0x7f)|0x80; +++ *p++ = v&0x7f; +++} +++ +++static unsigned int recover_key(unsigned char sample[4], int expected_size) +++{ +++ unsigned char plaintext[8] = { 'S', 'B' }; +++ put_v(plaintext+2, expected_size); +++ +++ return (sample[0]^plaintext[0])| +++ ((sample[1]^plaintext[1])<<8)| +++ ((sample[2]^plaintext[2])<<16)| +++ ((sample[3]^plaintext[3])<<24); +++} +++ +++static void xor_block(void *p1, void *p2, int size, int key, int *key_ptr) +++{ +++ int *d1 = p1; +++ int *d2 = p2; +++ int k = *key_ptr; +++ +++ size >>= 2; +++ +++ while (size--) { +++ *d2 = *d1 ^ k; +++ k += key; +++ d1++; +++ d2++; +++ } +++ +++ *key_ptr = k; +++} +++ +++static void decode_block(uint8_t *src, uint8_t *dest, int size, +++ uint32_t key, uint32_t *key_ptr, +++ int align) +++{ +++ int s = size; +++ char tmp[4]; +++ int a2; +++ +++ if (!size) +++ return; +++ +++ align &= 3; +++ a2 = (4 - align) & 3; +++ +++ if (align) { +++ uint32_t tmpkey = *key_ptr - key; +++ memcpy(tmp + align, src, a2); +++ xor_block(tmp, tmp, 4, key, &tmpkey); +++ memcpy(dest, tmp + align, a2); +++ s -= a2; +++ } +++ +++ if (s >= 4) { +++ if (!align) +++ align = 4; +++ xor_block(src + a2, dest + a2, s & ~3, +++ key, key_ptr); +++ s &= 3; +++ } +++ +++ if (s) { +++ size -= s; +++ memcpy(tmp, src + size, s); +++ xor_block(&tmp, &tmp, 4, key, key_ptr); +++ memcpy(dest + size, tmp, s); +++ } +++} +++ +++static uint32_t get_v(uint8_t *p) +++{ +++ uint32_t v = 0; +++ +++ do { +++ v <<= 7; +++ v += *p & 0x7f; +++ } while (*p++ & 0x80); +++ +++ return v; +++} +++ +++static uint8_t *read_vblock(AVIOContext *src, uint32_t *size, uint32_t key, uint32_t *k2, int align) +++{ +++ uint8_t tmp[4]; +++ uint8_t *buf; +++ unsigned n; +++ +++ if(avio_read(src, tmp, 4) != 4) +++ return NULL; +++ +++ decode_block(tmp, tmp, 4, key, k2, align); +++ +++ n = get_v(tmp); +++ +++ buf = av_malloc(n); +++ if (!buf) +++ return NULL; +++ +++ *size = n; +++ n -= 4; +++ +++ memcpy(buf, tmp, 4); +++ +++ if (avio_read(src, buf + 4, n) == n) { +++ decode_block(buf + 4, buf + 4, n, key, k2, align + 4); +++ } else { +++ av_free(buf); +++ buf = NULL; +++ } +++ +++ return buf; +++} +++ +++static uint8_t *read_sb_block(AVIOContext *src, unsigned *size, uint32_t *key, int expected_size) +++{ +++ uint8_t *buf; +++ uint8_t ibuf[8], sbuf[8]; +++ uint32_t k2; +++ int n; +++ +++ if (avio_read(src, ibuf, 8) < 8) +++ return NULL; +++ +++ k2 = *key; +++ decode_block(ibuf, sbuf, 8, *key, &k2, 0); +++ +++ n = get_v(sbuf+2); +++ +++ if (sbuf[0] != 'S' || sbuf[1] != 'B' || (expected_size>0 && n != expected_size)) { +++ uint32_t tmpkey = recover_key(ibuf, expected_size); +++ k2 = tmpkey; +++ decode_block(ibuf, sbuf, 8, tmpkey, &k2, 0); +++ n = get_v(sbuf+2); +++ if(sbuf[0] != 'S' || sbuf[1] != 'B' || expected_size != n) +++ return NULL; +++ *key = tmpkey; +++ } +++ +++ buf = av_malloc(n); +++ if (!buf) +++ return NULL; +++ +++ memcpy(buf, sbuf, 8); +++ +++ *size = n; +++ n -= 8; +++ +++ if (avio_read(src, buf+8, n) < n) { +++ av_free(buf); +++ return NULL; +++ } +++ +++ decode_block(buf + 8, buf + 8, n, *key, &k2, 0); +++ +++ return buf; +++} +++ +++static void track_header(VIV_DemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) +++{ +++ int i,j; +++ int64_t off; +++ int val_1; +++ int num_video, num_audio; +++ AVIOContext *pb=0; +++ +++ pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); +++ //ff_get_v(pb); // track_header_len +++ ffio_read_varlen(pb); // track_header_len +++ avio_r8(pb); // '1' +++ +++ //val_1 = ff_get_v(pb); +++ val_1 = ffio_read_varlen(pb); +++ +++ for(i=0;icodec; +++ +++ st->id = i; +++ +++ vcodec->codec_type = CODEC_TYPE_VIDEO; +++ vcodec->codec_id = CODEC_ID_VP6; +++ +++ off = avio_tell(pb); +++ //off += ff_get_v(pb); +++ off += ffio_read_varlen(pb); +++ avio_r8(pb); // '3' +++ avio_r8(pb); // val_7 +++ st->time_base.num = avio_rl32(pb); // frame_time +++ st->time_base.den = avio_rl32(pb); // time_base +++ st->nb_frames = avio_rl32(pb); // n frames +++ vcodec->width = avio_rl16(pb); // width +++ vcodec->height = avio_rl16(pb); // height +++ avio_r8(pb); // val_8 +++ avio_rl32(pb); // val_9 +++ +++ vcodec->flags |= CODEC_FLAG_GLOBAL_HEADER; // ? +++ +++ avio_seek(pb, off, SEEK_SET); +++ } +++ +++ off = avio_tell(pb); +++ //off += ff_get_v(pb); // val_10 +++ off += ffio_read_varlen(pb); // val_10 +++ avio_r8(pb); // '4' +++ num_audio = avio_r8(pb); +++ avio_seek(pb, off, SEEK_SET); +++ +++ if(num_audio != 1) +++ av_log(s, AV_LOG_WARNING, "viv: number of audio tracks %d is not 1\n", num_audio); +++ +++ for(i=0;icodec; +++ +++ st->id = num_video + i; +++ +++ acodec->codec_type = CODEC_TYPE_AUDIO; +++ acodec->codec_id = CODEC_ID_VORBIS; +++ acodec->flags |= CODEC_FLAG_GLOBAL_HEADER; // ? +++ +++ off = avio_tell(pb); +++ //off += ff_get_v(pb); // length +++ off += ffio_read_varlen(pb); // length +++ avio_r8(pb); // '5' +++ avio_r8(pb); //codec_id +++ avio_rl16(pb); //codec_subid +++ acodec->channels = avio_rl16(pb); // channels +++ acodec->sample_rate = avio_rl32(pb); // sample_rate +++ avio_seek(pb, 10, SEEK_CUR); // data_1 +++ q = avio_r8(pb); +++ avio_seek(pb, q, SEEK_CUR); // data_2 +++ avio_r8(pb); // zeropad +++ +++ if(avio_tell(pb) < off) { +++ int num_data; +++ int xd_size = 0; +++ int data_len[256]; +++ uint8_t * p; +++ int offset = 1; +++ //ff_get_v(pb); // val_13 +++ ffio_read_varlen(pb); // val_13 +++ avio_r8(pb); // '19' +++ //ff_get_v(pb); // len_3 +++ ffio_read_varlen(pb); // len_3 +++ num_data = avio_r8(pb); +++ for(j=0;jextradata_size = 64 + xd_size + xd_size / 255; +++ acodec->extradata = (uint8_t*)av_mallocz(acodec->extradata_size); +++ +++ p = acodec->extradata; +++ p[0] = 2; +++ +++ for(j=0;jextradata_size = offset; +++ } +++ } +++ +++ av_free(pb); +++} +++ +++static void track_index(VIV_DemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) +++{ +++ int i; +++ int64_t off; +++ int poff; +++ int maxnp=0; +++ AVIOContext *pb=0; +++ +++ pb = avio_alloc_context(buf, size, 0, NULL, NULL, NULL, NULL); +++ //ff_get_v(pb); // track_index_len +++ ffio_read_varlen(pb); // track_index_len +++ avio_r8(pb); // 'c' +++ //viv->n_sb_blocks = ff_get_v(pb); +++ viv->n_sb_blocks = ffio_read_varlen(pb); +++ viv->sb_blocks = av_mallocz(sizeof(VIV_SB_block) * viv->n_sb_blocks); +++ if(!viv->sb_blocks) { +++ viv->n_sb_blocks = 0; +++ av_free(pb); +++ return; +++ } +++ +++ off = 0; +++ poff = 0; +++ +++ for(i=0;in_sb_blocks;i++) { +++ viv->sb_blocks[i].byte_offset = off; +++ viv->sb_blocks[i].packet_offset = poff; +++ +++ //viv->sb_blocks[i].size = ff_get_v(pb); +++ //viv->sb_blocks[i].n_packets = ff_get_v(pb); +++ viv->sb_blocks[i].size = ffio_read_varlen(pb); +++ viv->sb_blocks[i].n_packets = ffio_read_varlen(pb); +++ +++ off += viv->sb_blocks[i].size; +++ poff += viv->sb_blocks[i].n_packets; +++ +++ +++ if(maxnp < viv->sb_blocks[i].n_packets) +++ maxnp = viv->sb_blocks[i].n_packets; +++ } +++ +++ viv->sb_entries = av_mallocz(maxnp * sizeof(VIV_SB_entry)); +++ av_free(pb); +++} +++ +++static void load_sb_block(AVFormatContext *s, VIV_DemuxContext *viv, int expected_size) +++{ +++ uint32_t size=0; +++ int i; +++ AVIOContext *pb = 0; +++ if(viv->sb_pb) { +++ av_free(viv->sb_pb); +++ viv->sb_pb = NULL; +++ } +++ +++ if(viv->sb_buf) +++ av_free(viv->sb_buf); +++ +++ viv->sb_buf = read_sb_block(s->pb, &size, &viv->sb_key, expected_size); +++ if(!viv->sb_buf) { +++ return; +++ } +++ +++ pb = avio_alloc_context(viv->sb_buf, size, 0, NULL, NULL, NULL, NULL); +++ viv->sb_pb = pb; +++ +++ avio_r8(pb); // 'S' +++ avio_r8(pb); // 'B' +++ //ff_get_v(pb); // size +++ ffio_read_varlen(pb); // size +++ avio_r8(pb); // junk +++ //ff_get_v(pb); // first packet +++ ffio_read_varlen(pb); // first packet +++ +++ viv->n_sb_entries = viv->sb_blocks[viv->current_sb].n_packets; +++ +++ for(i=0;in_sb_entries;i++) { +++ //viv->sb_entries[i].size = ff_get_v(pb); +++ viv->sb_entries[i].size = ffio_read_varlen(pb); +++ viv->sb_entries[i].flag = avio_r8(pb); +++ } +++ +++ //ff_get_v(pb); // 0 +++ ffio_read_varlen(pb); // 0 +++ avio_r8(pb); // 0 +++ +++ viv->current_sb_entry = 0; +++} +++ +++static int viv_read_header(AVFormatContext *s, +++ AVFormatParameters *ap) +++{ +++ VIV_DemuxContext *viv = s->priv_data; +++ AVIOContext *pb = s->pb; +++ int64_t header_end; +++ int num_tracks; +++ uint32_t key, k2; +++ uint32_t v; +++ uint8_t keybuffer[187]; +++ uint32_t b22_size = 0; +++ uint32_t b22_key = 0; +++ uint8_t *buf = 0; +++ +++ // string "vividas03" +++ avio_seek(pb, 9, SEEK_CUR); +++ +++ header_end = avio_tell(pb); +++ +++ // v: header size +++ //header_end += ff_get_v(pb); +++ header_end += ffio_read_varlen(pb); +++ +++ // u8: n tracks +++ num_tracks = avio_r8(pb); +++ +++ if(num_tracks != 1) { +++ av_log(s, AV_LOG_ERROR, "number of tracks %d is not 1\n", num_tracks); +++ return AVERROR(EINVAL); +++ } +++ +++ v = avio_r8(pb); +++ avio_seek(pb, v, SEEK_CUR); +++ +++ avio_read(pb, keybuffer, 187); +++ key = decode_key(keybuffer); +++ viv->sb_key = key; +++ +++ avio_rl32(pb); // track_header_len +++ +++ for(;;) { +++ int64_t here = avio_tell(pb); +++ int block_len, block_type; +++ +++ if(here >= header_end) +++ break; +++ +++ //block_len = ff_get_v(pb); +++ block_len = ffio_read_varlen(pb); +++ block_type = avio_r8(pb); +++ +++ if(block_type == 22) { +++ avio_read(pb, keybuffer, 187); +++ b22_key = decode_key(keybuffer); +++ b22_size = avio_rl32(pb); +++ } +++ +++ avio_seek(pb, here + block_len, SEEK_SET); +++ } +++ +++ if(b22_size) { +++ k2 = b22_key; +++ buf = read_vblock(pb, &v, b22_key, &k2, 0); +++ if(!buf) +++ return AVERROR(EIO); +++ +++ av_free(buf); +++ } +++ +++ k2 = key; +++ buf = read_vblock(pb, &v, key, &k2, 0); +++ if(!buf) +++ return AVERROR(EIO); +++ track_header(viv, s, buf, v); +++ av_free(buf); +++ +++ buf = read_vblock(pb, &v, key, &k2, v); +++ if(!buf) +++ return AVERROR(EIO); +++ track_index(viv, s, buf, v); +++ av_free(buf); +++ +++ viv->sb_offset = avio_tell(pb); +++ if(viv->n_sb_blocks > 0) { +++ viv->current_sb = 0; +++ load_sb_block(s, viv, viv->sb_blocks[0].size); +++ } else { +++ viv->current_sb = -1; +++ } +++ +++ return 0; +++} +++ +++static int viv_read_packet(AVFormatContext *s, +++ AVPacket *pkt) +++{ +++ VIV_DemuxContext *viv = s->priv_data; +++ AVIOContext *pb; +++ int64_t off; +++ +++ if(viv->current_audio_subpacket < viv->n_audio_subpackets) { +++ // audio packets +++ AVStream *astream; +++ int size = viv->audio_subpackets[viv->current_audio_subpacket+1].start - viv->audio_subpackets[viv->current_audio_subpacket].start; +++ pb = viv->sb_pb; +++ av_get_packet(pb, pkt, size); +++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; +++ +++ pkt->stream_index = 1; +++ astream = s->streams[pkt->stream_index]; +++ +++ pkt->pts = viv->audio_sample * (long long)astream->time_base.den / (long long)astream->time_base.num / (long long)astream->codec->sample_rate; +++ viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / astream->codec->channels; +++ pkt->flags |= AV_PKT_FLAG_KEY; +++ viv->current_audio_subpacket++; +++ return 0; +++ } +++ +++ if(viv->current_sb_entry >= viv->n_sb_entries) { +++ if(viv->current_sb+1 >= viv->n_sb_blocks) +++ return AVERROR(EIO); +++ viv->current_sb++; +++ +++ load_sb_block(s, viv, 0); +++ viv->current_sb_entry = 0; +++ } +++ +++ pb = viv->sb_pb; +++ off = avio_tell(pb); +++ off += viv->sb_entries[viv->current_sb_entry].size; +++ +++ if(viv->sb_entries[viv->current_sb_entry].flag == 0) { +++ // A/V packet +++ int i; +++ //int v_size = ff_get_v(pb); +++ int v_size = ffio_read_varlen(pb); +++ ///*int a_size = */ff_get_v(pb); +++ /*int a_size = */ffio_read_varlen(pb); +++ av_get_packet(pb, pkt, v_size); +++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; +++ +++ pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; +++ pkt->flags |= (pkt->data[0]&0x80)?0:AV_PKT_FLAG_KEY; +++ pkt->stream_index = 0; +++ +++ for(i=0;i 0 && start == 0) +++ break; +++ +++ viv->n_audio_subpackets = i+1; +++ viv->audio_subpackets[i].start = start; +++ viv->audio_subpackets[i].pcm_bytes = pcm_bytes; +++ } +++ viv->audio_subpackets[viv->n_audio_subpackets].start = (int)(off - avio_tell(pb)); +++ viv->current_audio_subpacket = 0; +++ //viv->n_audio_subpackets = 0; +++ //avio_seek(pb, off, SEEK_SET); +++ +++ } else { +++ // V packet +++ //int v_size = ff_get_v(pb); +++ int v_size = ffio_read_varlen(pb); +++ av_get_packet(pb, pkt, v_size); +++ pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; +++ pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; +++ pkt->flags |= (pkt->data[0]&0x80)?0:AV_PKT_FLAG_KEY; +++ pkt->stream_index = 0; +++ } +++ +++ viv->current_sb_entry++; +++ +++// avio_seek(pb, off, SEEK_SET); +++ +++ return 0; +++} +++ +++static int viv_read_close(AVFormatContext *s) +++{ +++ VIV_DemuxContext *viv = s->priv_data; +++ if(viv->sb_pb) +++ av_free(viv->sb_pb); +++ +++ if(viv->sb_buf) +++ av_free(viv->sb_buf); +++ +++ if(viv->sb_blocks) +++ av_free(viv->sb_blocks); +++ +++ if(viv->sb_entries) +++ av_free(viv->sb_entries); +++ +++ return 0; +++} +++ +++static int viv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +++{ +++ VIV_DemuxContext *viv = s->priv_data; +++ int frame = 0; +++ int i; +++ +++ if(stream_index == 0) +++ frame = (int)timestamp; +++ else +++ frame = (int)timestamp * s->streams[stream_index]->time_base.den * s->streams[0]->time_base.num / s->streams[stream_index]->time_base.num / s->streams[0]->time_base.den; +++ +++ for(i=0;in_sb_blocks;i++) { +++ if(frame >= viv->sb_blocks[i].packet_offset && frame < viv->sb_blocks[i].packet_offset + viv->sb_blocks[i].n_packets) { +++ // flush audio packet queue +++ viv->current_audio_subpacket = 0; +++ viv->n_audio_subpackets = 0; +++ viv->current_sb = i; +++ // seek to ith sb block +++ avio_seek(s->pb, viv->sb_offset + viv->sb_blocks[i].byte_offset, SEEK_SET); +++ // load the block +++ load_sb_block(s, viv, 0); +++ // most problematic part: guess audio offset +++ viv->audio_sample = (int64_t)viv->sb_blocks[i].packet_offset * (int64_t)s->streams[1]->codec->sample_rate * s->streams[0]->time_base.num / s->streams[0]->time_base.den; +++ // hand-tuned 1.3s a/v offset +++ viv->audio_sample += 1300 * s->streams[1]->codec->sample_rate / 1000; +++ viv->current_sb_entry = 0; +++ return 1; +++ } +++ } +++ return 0; +++} +++ +++AVInputFormat ff_vividas_demuxer = { +++ "vividas", +++ "Vividas VIV format", +++ sizeof(VIV_DemuxContext), +++ viv_probe, +++ viv_read_header, +++ viv_read_packet, +++ viv_read_close, +++ viv_read_seek +++}; +++ +-- +1.7.9.5 +