|
|
|
@@ -52,16 +52,24 @@ typedef struct { |
|
|
|
} codebook_t; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
int channels; |
|
|
|
int sample_rate; |
|
|
|
int blocksize[2]; |
|
|
|
|
|
|
|
int ncodebooks; |
|
|
|
codebook_t * codebooks; |
|
|
|
} venc_context_t; |
|
|
|
|
|
|
|
static inline int ilog(int a) { |
|
|
|
static inline int ilog(unsigned int a) { |
|
|
|
int i; |
|
|
|
for (i = 0; (a >> i) > 0; i++); |
|
|
|
for (i = 0; a >> i; i++); |
|
|
|
return i; |
|
|
|
} |
|
|
|
|
|
|
|
static void put_float(PutBitContext * pb, float f) { |
|
|
|
put_bits(pb, 32, *(uint32_t*)&f); |
|
|
|
} |
|
|
|
|
|
|
|
static void put_codebook_header(PutBitContext * pb, codebook_t * cb) { |
|
|
|
int i; |
|
|
|
int ordered = 0; |
|
|
|
@@ -71,7 +79,7 @@ static void put_codebook_header(PutBitContext * pb, codebook_t * cb) { |
|
|
|
put_bits(pb, 24, cb->nentries); |
|
|
|
|
|
|
|
for (i = 1; i < cb->nentries; i++) if (cb->entries[i].len < cb->entries[i-1].len) break; |
|
|
|
if (i == cb->entires) ordered = 1; |
|
|
|
if (i == cb->nentries) ordered = 1; |
|
|
|
|
|
|
|
put_bits(pb, 1, ordered); |
|
|
|
if (ordered) { |
|
|
|
@@ -79,6 +87,7 @@ static void put_codebook_header(PutBitContext * pb, codebook_t * cb) { |
|
|
|
put_bits(pb, 5, len); |
|
|
|
i = 0; |
|
|
|
while (i < cb->nentries) { |
|
|
|
int j; |
|
|
|
for (j = 0; j+i < cb->nentries; j++) if (cb->entries[j+i].len != len) break; |
|
|
|
put_bits(pb, 5, j); |
|
|
|
i += j; |
|
|
|
@@ -87,7 +96,7 @@ static void put_codebook_header(PutBitContext * pb, codebook_t * cb) { |
|
|
|
} else { |
|
|
|
int sparse = 0; |
|
|
|
for (i = 0; i < cb->nentries; i++) if (!cb->entries[i].len) break; |
|
|
|
if (i != cb->entires) sparse = 1; |
|
|
|
if (i != cb->nentries) sparse = 1; |
|
|
|
put_bits(pb, 1, sparse); |
|
|
|
|
|
|
|
for (i = 0; i < cb->nentries; i++) { |
|
|
|
@@ -111,50 +120,95 @@ static void put_codebook_header(PutBitContext * pb, codebook_t * cb) { |
|
|
|
|
|
|
|
for (i = 1; i < tmp; i++) bits = FFMIN(bits, ilog(cb->quantlist[i])); |
|
|
|
|
|
|
|
put_float(bc, cb->min); |
|
|
|
put_float(bc, cb->delta); |
|
|
|
put_float(pb, cb->min); |
|
|
|
put_float(pb, cb->delta); |
|
|
|
|
|
|
|
put_bits(bc, 4, bits - 1); |
|
|
|
put_bits(bc, 1, seq_p); |
|
|
|
put_bits(pb, 4, bits - 1); |
|
|
|
put_bits(pb, 1, cb->seq_p); |
|
|
|
|
|
|
|
for (i = 0; i < tmp; i++) put_bits(bc, bits, cb->quantlist[i]) |
|
|
|
for (i = 0; i < tmp; i++) put_bits(pb, bits, cb->quantlist[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void put_main_header(PutBitContext * pb, venc_context_t * venc) { |
|
|
|
static int put_main_header(venc_context_t * venc, uint8_t ** out) { |
|
|
|
int i; |
|
|
|
put_bits(pb, 8, 5); //magic |
|
|
|
for (i = 0; "vorbis"[i]; i++) put_bits(pb, 8, "vorbis"[i]); |
|
|
|
PutBitContext pb; |
|
|
|
uint8_t buffer[50000] = {0}, * p = buffer; |
|
|
|
int buffer_len = sizeof buffer; |
|
|
|
int len, hlens[3]; |
|
|
|
|
|
|
|
// identification header |
|
|
|
init_put_bits(&pb, p, buffer_len); |
|
|
|
put_bits(&pb, 8, 1); //magic |
|
|
|
for (i = 0; "vorbis"[i]; i++) put_bits(&pb, 8, "vorbis"[i]); |
|
|
|
put_bits(&pb, 32, 0); // version |
|
|
|
put_bits(&pb, 8, venc->channels); |
|
|
|
put_bits(&pb, 32, venc->sample_rate); |
|
|
|
put_bits(&pb, 32, 0); // bitrate |
|
|
|
put_bits(&pb, 32, 0); // bitrate |
|
|
|
put_bits(&pb, 32, 0); // bitrate |
|
|
|
put_bits(&pb, 4, venc->blocksize[0]); |
|
|
|
put_bits(&pb, 4, venc->blocksize[1]); |
|
|
|
put_bits(&pb, 1, 1); // framing |
|
|
|
|
|
|
|
flush_put_bits(&pb); |
|
|
|
hlens[0] = (put_bits_count(&pb) + 7) / 8; |
|
|
|
buffer_len -= hlens[0]; |
|
|
|
p += hlens[0]; |
|
|
|
|
|
|
|
// comment header |
|
|
|
init_put_bits(&pb, p, buffer_len); |
|
|
|
put_bits(&pb, 8, 3); //magic |
|
|
|
for (i = 0; "vorbis"[i]; i++) put_bits(&pb, 8, "vorbis"[i]); |
|
|
|
put_bits(&pb, 32, 0); // vendor length TODO |
|
|
|
put_bits(&pb, 32, 0); // amount of comments |
|
|
|
put_bits(&pb, 1, 1); // framing |
|
|
|
|
|
|
|
flush_put_bits(&pb); |
|
|
|
hlens[1] = (put_bits_count(&pb) + 7) / 8; |
|
|
|
buffer_len -= hlens[1]; |
|
|
|
p += hlens[1]; |
|
|
|
|
|
|
|
// setup header |
|
|
|
init_put_bits(&pb, p, buffer_len); |
|
|
|
put_bits(&pb, 8, 5); //magic |
|
|
|
for (i = 0; "vorbis"[i]; i++) put_bits(&pb, 8, "vorbis"[i]); |
|
|
|
|
|
|
|
// codebooks |
|
|
|
put_bits(&pb, 8, venc->ncodebooks - 1); |
|
|
|
for (i = 0; i < venc->ncodebooks; i++) put_codebook_header(&pb, &venc->codebooks[0]); |
|
|
|
|
|
|
|
|
|
|
|
flush_put_bits(&pb); |
|
|
|
hlens[2] = (put_bits_count(&pb) + 7) / 8; |
|
|
|
|
|
|
|
len = hlens[0] + hlens[1] + hlens[2]; |
|
|
|
p = *out = av_mallocz(64 + len + len/255); |
|
|
|
|
|
|
|
*p++ = 2; |
|
|
|
p += av_xiphlacing(p, hlens[0]); |
|
|
|
p += av_xiphlacing(p, hlens[1]); |
|
|
|
buffer_len = 0; |
|
|
|
for (i = 0; i < 3; i++) { |
|
|
|
memcpy(p, buffer + buffer_len, hlens[i]); |
|
|
|
p += hlens[i]; |
|
|
|
buffer_len += hlens[i]; |
|
|
|
} |
|
|
|
|
|
|
|
put_bits(pb, 8, venc->ncodebooks - 1); |
|
|
|
for (i = 0; i < venc->ncodebooks; i++) put_codebook_header(pb, venc->codebooks[0]); |
|
|
|
return p - *out; |
|
|
|
} |
|
|
|
|
|
|
|
static int vorbis_encode_init(AVCodecContext * avccontext) |
|
|
|
{ |
|
|
|
venc_context_t * venc = avccontext->priv_data; |
|
|
|
uint8_t *p; |
|
|
|
unsigned int offset, len; |
|
|
|
|
|
|
|
avccontext->channels; |
|
|
|
avccontext->sample_rate; |
|
|
|
venc->channels = avccontext->channels; |
|
|
|
venc->sample_rate = avccontext->sample_rate; |
|
|
|
|
|
|
|
//if (avccontext->flags & CODEC_FLAG_QSCALE) avccontext->global_quality / (float)FF_QP2LAMBDA); else avccontext->bit_rate; |
|
|
|
//if(avccontext->cutoff > 0) cfreq = avccontext->cutoff / 1000.0; |
|
|
|
|
|
|
|
len = header.bytes + header_comm.bytes + header_code.bytes; |
|
|
|
|
|
|
|
p = avccontext->extradata = av_mallocz(64 + len + len/255); |
|
|
|
p[0] = 2; |
|
|
|
offset = 1; |
|
|
|
offset += av_xiphlacing(&p[offset], header.bytes); |
|
|
|
offset += av_xiphlacing(&p[offset], header_comm.bytes); |
|
|
|
memcpy(&p[offset], header.packet, header.bytes); |
|
|
|
offset += header.bytes; |
|
|
|
memcpy(&p[offset], header_comm.packet, header_comm.bytes); |
|
|
|
offset += header_comm.bytes; |
|
|
|
memcpy(&p[offset], header_code.packet, header_code.bytes); |
|
|
|
offset += header_code.bytes; |
|
|
|
avccontext->extradata_size = offset; |
|
|
|
avccontext->extradata_size = put_main_header(venc, (uint8_t**)&avccontext->extradata); |
|
|
|
|
|
|
|
avccontext->frame_size = VORBIS_FRAME_SIZE; |
|
|
|
|
|
|
|
@@ -167,17 +221,15 @@ static int vorbis_encode_init(AVCodecContext * avccontext) |
|
|
|
|
|
|
|
static int vorbis_encode_frame(AVCodecContext * avccontext, unsigned char * packets, int buf_size, void *data) |
|
|
|
{ |
|
|
|
#if 0 |
|
|
|
venc_context_t * venc = avccontext->priv_data; |
|
|
|
signed short * audio = data; |
|
|
|
int l, samples = data ? VORBIS_FRAME_SIZE : 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!l) return 0; |
|
|
|
int samples = data ? VORBIS_FRAME_SIZE : 0; |
|
|
|
|
|
|
|
avccontext->coded_frame->pts = av_rescale_q(op2->granulepos, (AVRational){1, avccontext->sample_rate}, avccontext->time_base); |
|
|
|
memcpy(packets, compressed_frame, l); |
|
|
|
return l; |
|
|
|
#endif |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|