?? adpcm.c
字號:
const int div = (sample - predictor) / step; const int nmin = av_clip(div-range, -8, 6); const int nmax = av_clip(div+range, -7, 7); for(nidx=nmin; nidx<=nmax; nidx++) { const int nibble = nidx & 0xf; int dec_sample = predictor + nidx * step;#define STORE_NODE(NAME, STEP_INDEX)\ int d;\ uint32_t ssd;\ dec_sample = av_clip_int16(dec_sample);\ d = sample - dec_sample;\ ssd = nodes[j]->ssd + d*d;\ if(nodes_next[frontier-1] && ssd >= nodes_next[frontier-1]->ssd)\ continue;\ /* Collapse any two states with the same previous sample value. \ * One could also distinguish states by step and by 2nd to last * sample, but the effects of that are negligible. */\ for(k=0; k<frontier && nodes_next[k]; k++) {\ if(dec_sample == nodes_next[k]->sample1) {\ assert(ssd >= nodes_next[k]->ssd);\ goto next_##NAME;\ }\ }\ for(k=0; k<frontier; k++) {\ if(!nodes_next[k] || ssd < nodes_next[k]->ssd) {\ TrellisNode *u = nodes_next[frontier-1];\ if(!u) {\ assert(pathn < max_paths);\ u = t++;\ u->path = pathn++;\ }\ u->ssd = ssd;\ u->step = STEP_INDEX;\ u->sample2 = nodes[j]->sample1;\ u->sample1 = dec_sample;\ paths[u->path].nibble = nibble;\ paths[u->path].prev = nodes[j]->path;\ memmove(&nodes_next[k+1], &nodes_next[k], (frontier-k-1)*sizeof(TrellisNode*));\ nodes_next[k] = u;\ break;\ }\ }\ next_##NAME:; STORE_NODE(ms, FFMAX(16, (AdaptationTable[nibble] * step) >> 8)); } } else if((version == CODEC_ID_ADPCM_IMA_WAV)|| (version == CODEC_ID_ADPCM_IMA_QT)|| (version == CODEC_ID_ADPCM_SWF)) {#define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\ const int predictor = nodes[j]->sample1;\ const int div = (sample - predictor) * 4 / STEP_TABLE;\ int nmin = av_clip(div-range, -7, 6);\ int nmax = av_clip(div+range, -6, 7);\ if(nmin<=0) nmin--; /* distinguish -0 from +0 */\ if(nmax<0) nmax--;\ for(nidx=nmin; nidx<=nmax; nidx++) {\ const int nibble = nidx<0 ? 7-nidx : nidx;\ int dec_sample = predictor + (STEP_TABLE * yamaha_difflookup[nibble]) / 8;\ STORE_NODE(NAME, STEP_INDEX);\ } LOOP_NODES(ima, step_table[step], av_clip(step + index_table[nibble], 0, 88)); } else { //CODEC_ID_ADPCM_YAMAHA LOOP_NODES(yamaha, step, av_clip((step * yamaha_indexscale[nibble]) >> 8, 127, 24567));#undef LOOP_NODES#undef STORE_NODE } } u = nodes; nodes = nodes_next; nodes_next = u; // prevent overflow if(nodes[0]->ssd > (1<<28)) { for(j=1; j<frontier && nodes[j]; j++) nodes[j]->ssd -= nodes[0]->ssd; nodes[0]->ssd = 0; } // merge old paths to save memory if(i == froze + FREEZE_INTERVAL) { p = &paths[nodes[0]->path]; for(k=i; k>froze; k--) { dst[k] = p->nibble; p = &paths[p->prev]; } froze = i; pathn = 0; // other nodes might use paths that don't coincide with the frozen one. // checking which nodes do so is too slow, so just kill them all. // this also slightly improves quality, but I don't know why. memset(nodes+1, 0, (frontier-1)*sizeof(TrellisNode*)); } } p = &paths[nodes[0]->path]; for(i=n-1; i>froze; i--) { dst[i] = p->nibble; p = &paths[p->prev]; } c->predictor = nodes[0]->sample1; c->sample1 = nodes[0]->sample1; c->sample2 = nodes[0]->sample2; c->step_index = nodes[0]->step; c->step = nodes[0]->step; c->idelta = nodes[0]->step;}static int adpcm_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data){ int n, i, st; short *samples; unsigned char *dst; ADPCMContext *c = avctx->priv_data; dst = frame; samples = (short *)data; st= avctx->channels == 2;/* n = (BLKSIZE - 4 * avctx->channels) / (2 * 8 * avctx->channels); */ switch(avctx->codec->id) { case CODEC_ID_ADPCM_IMA_WAV: n = avctx->frame_size / 8; c->status[0].prev_sample = (signed short)samples[0]; /* XXX *//* c->status[0].step_index = 0; *//* XXX: not sure how to init the state machine */ bytestream_put_le16(&dst, c->status[0].prev_sample); *dst++ = (unsigned char)c->status[0].step_index; *dst++ = 0; /* unknown */ samples++; if (avctx->channels == 2) { c->status[1].prev_sample = (signed short)samples[0];/* c->status[1].step_index = 0; */ bytestream_put_le16(&dst, c->status[1].prev_sample); *dst++ = (unsigned char)c->status[1].step_index; *dst++ = 0; samples++; } /* stereo: 4 bytes (8 samples) for left, 4 bytes for right, 4 bytes left, ... */ if(avctx->trellis > 0) { uint8_t buf[2][n*8]; adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n*8); if(avctx->channels == 2) adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n*8); for(i=0; i<n; i++) { *dst++ = buf[0][8*i+0] | (buf[0][8*i+1] << 4); *dst++ = buf[0][8*i+2] | (buf[0][8*i+3] << 4); *dst++ = buf[0][8*i+4] | (buf[0][8*i+5] << 4); *dst++ = buf[0][8*i+6] | (buf[0][8*i+7] << 4); if (avctx->channels == 2) { *dst++ = buf[1][8*i+0] | (buf[1][8*i+1] << 4); *dst++ = buf[1][8*i+2] | (buf[1][8*i+3] << 4); *dst++ = buf[1][8*i+4] | (buf[1][8*i+5] << 4); *dst++ = buf[1][8*i+6] | (buf[1][8*i+7] << 4); } } } else for (; n>0; n--) { *dst = adpcm_ima_compress_sample(&c->status[0], samples[0]); *dst |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 2]); *dst |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 3]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 4]); *dst |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 5]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 6]); *dst |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 7]) << 4; dst++; /* right channel */ if (avctx->channels == 2) { *dst = adpcm_ima_compress_sample(&c->status[1], samples[1]); *dst |= adpcm_ima_compress_sample(&c->status[1], samples[3]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[1], samples[5]); *dst |= adpcm_ima_compress_sample(&c->status[1], samples[7]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[1], samples[9]); *dst |= adpcm_ima_compress_sample(&c->status[1], samples[11]) << 4; dst++; *dst = adpcm_ima_compress_sample(&c->status[1], samples[13]); *dst |= adpcm_ima_compress_sample(&c->status[1], samples[15]) << 4; dst++; } samples += 8 * avctx->channels; } break; case CODEC_ID_ADPCM_IMA_QT: { int ch, i; PutBitContext pb; init_put_bits(&pb, dst, buf_size*8); for(ch=0; ch<avctx->channels; ch++){ put_bits(&pb, 9, (c->status[ch].prev_sample + 0x10000) >> 7); put_bits(&pb, 7, c->status[ch].step_index); if(avctx->trellis > 0) { uint8_t buf[64]; adpcm_compress_trellis(avctx, samples+ch, buf, &c->status[ch], 64); for(i=0; i<64; i++) put_bits(&pb, 4, buf[i^1]); c->status[ch].prev_sample = c->status[ch].predictor & ~0x7F; } else { for (i=0; i<64; i+=2){ int t1, t2; t1 = adpcm_ima_compress_sample(&c->status[ch], samples[avctx->channels*(i+0)+ch]); t2 = adpcm_ima_compress_sample(&c->status[ch], samples[avctx->channels*(i+1)+ch]); put_bits(&pb, 4, t2); put_bits(&pb, 4, t1); } c->status[ch].prev_sample &= ~0x7F; } } dst += put_bits_count(&pb)>>3; break; } case CODEC_ID_ADPCM_SWF: { int i; PutBitContext pb; init_put_bits(&pb, dst, buf_size*8); n = avctx->frame_size-1; //Store AdpcmCodeSize put_bits(&pb, 2, 2); //Set 4bits flash adpcm format //Init the encoder state for(i=0; i<avctx->channels; i++){ c->status[i].step_index = av_clip(c->status[i].step_index, 0, 63); // clip step so it fits 6 bits put_bits(&pb, 16, samples[i] & 0xFFFF); put_bits(&pb, 6, c->status[i].step_index); c->status[i].prev_sample = (signed short)samples[i]; } if(avctx->trellis > 0) { uint8_t buf[2][n]; adpcm_compress_trellis(avctx, samples+2, buf[0], &c->status[0], n); if (avctx->channels == 2) adpcm_compress_trellis(avctx, samples+3, buf[1], &c->status[1], n); for(i=0; i<n; i++) { put_bits(&pb, 4, buf[0][i]); if (avctx->channels == 2) put_bits(&pb, 4, buf[1][i]); } } else { for (i=1; i<avctx->frame_size; i++) { put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels*i])); if (avctx->channels == 2) put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1], samples[2*i+1])); } } flush_put_bits(&pb); dst += put_bits_count(&pb)>>3; break; } case CODEC_ID_ADPCM_MS: for(i=0; i<avctx->channels; i++){ int predictor=0; *dst++ = predictor; c->status[i].coeff1 = AdaptCoeff1[predictor]; c->status[i].coeff2 = AdaptCoeff2[predictor]; } for(i=0; i<avctx->channels; i++){ if (c->status[i].idelta < 16) c->status[i].idelta = 16; bytestream_put_le16(&dst, c->status[i].idelta); } for(i=0; i<avctx->channels; i++){ c->status[i].sample1= *samples++; bytestream_put_le16(&dst, c->status[i].sample1); } for(i=0; i<avctx->channels; i++){ c->status[i].sample2= *samples++; bytestream_put_le16(&dst, c->status[i].sample2); } if(avctx->trellis > 0) { int n = avctx->block_align - 7*avctx->channels; uint8_t buf[2][n]; if(avctx->channels == 1) { n *= 2; adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n); for(i=0; i<n; i+=2) *dst++ = (buf[0][i] << 4) | buf[0][i+1]; } else { adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n); adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n); for(i=0; i<n; i++) *dst++ = (buf[0][i] << 4) | buf[1][i]; } } else for(i=7*avctx->channels; i<avctx->block_align; i++) { int nibble; nibble = adpcm_ms_compress_sample(&c->status[ 0], *samples++)<<4; nibble|= adpcm_ms_compress_sample(&c->status[st], *samples++); *dst++ = nibble; } break; case CODEC_ID_ADPCM_YAMAHA: n = avctx->frame_size / 2; if(avctx->trellis > 0) { uint8_t buf[2][n*2]; n *= 2; if(avctx->channels == 1) { adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n); for(i=0; i<n; i+=2) *dst++ = buf[0][i] | (buf[0][i+1] << 4); } else { adpcm_compress_trellis(avctx, samples, buf[0], &c->status[0], n); adpcm_compress_trellis(avctx, samples+1, buf[1], &c->status[1], n); for(i=0; i<n; i++) *dst++ = buf[0][i] | (buf[1][i] << 4); } } else for (; n>0; n--) { for(i = 0; i < avctx->channels; i++) { int nibble; nibble = adpcm_yamaha_compress_sample(&c->status[i], samples[i]); nibble |= adpcm_yamaha_compress_sample(&c->status[i], samples[i+avctx->channels]) << 4; *dst++ = nibble; } samples += 2 * avctx->channels; } break; default: return -1;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -