static audio_channel *libavcodec_compress(void *state, audio_channel * channel) { struct libavcodec_codec_state *s = (struct libavcodec_codec_state *) state; assert(s->magic == MAGIC); if(channel) { if(!audio_desc_eq(s->saved_desc, audio_desc_from_audio_channel(channel))) { if(!reinitialize_coder(s, audio_desc_from_audio_channel(channel))) { fprintf(stderr, "Unable to reinitialize audio compress!\n"); return NULL; } } if(s->change_bps_to) { change_bps(s->tmp.data, s->saved_desc.bps, channel->data, s->change_bps_to, channel->data_len); s->tmp.data_len += channel->data_len / s->saved_desc.bps * s->change_bps_to; } else { memcpy(s->tmp.data + s->tmp.data_len, channel->data, channel->data_len); s->tmp.data_len += channel->data_len; } } int bps = s->output_channel.bps; int offset = 0; s->output_channel.data_len = 0; int chunk_size = s->codec_ctx->frame_size * bps; //while(offset + chunk_size <= s->tmp.data_len) { while(offset + chunk_size <= s->tmp.data_len) { s->pkt.data = (unsigned char *) s->output_channel.data + s->output_channel.data_len; s->pkt.size = 1024*1024 - s->output_channel.data_len; int got_packet; memcpy(s->samples, s->tmp.data + offset, chunk_size); int ret = avcodec_encode_audio2(s->codec_ctx, &s->pkt, s->av_frame, &got_packet); if(ret) { char errbuf[1024]; av_strerror(ret, errbuf, sizeof(errbuf)); fprintf(stderr, "Warning: unable to compress audio: %s\n", errbuf); } if(got_packet) { s->output_channel.data_len += s->pkt.size; } offset += chunk_size; if(!(s->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) break; } s->tmp.data_len -= offset; memmove(s->tmp.data, s->tmp.data + offset, s->tmp.data_len); ///fprintf(stderr, "%d %d\n", i++% 2, s->output_channel.data_len); if(s->output_channel.data_len) { return &s->output_channel; } else { return NULL; } }
// Filter data through filter static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* l = af->data; // Local data struct mp_audio* c = data; // Current working data int len = c->len/c->bps; // Length in samples of current audio block if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) return NULL; // Change to cpu native endian format if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) endian(c->audio,c->audio,len,c->bps); // Conversion table if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { float2int(c->audio, l->audio, len, l->bps); if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) si2us(l->audio,len,l->bps); } else { // Input must be int // Change signed/unsigned if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ si2us(c->audio,len,c->bps); } // Convert to special formats switch(l->format&AF_FORMAT_POINT_MASK){ case(AF_FORMAT_F): int2float(c->audio, l->audio, len, c->bps); break; default: // Change the number of bits if(c->bps != l->bps) change_bps(c->audio,l->audio,len,c->bps,l->bps); else memcpy(l->audio,c->audio,len*c->bps); break; } } // Switch from cpu native endian to the correct endianness if((l->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) endian(l->audio,l->audio,len,l->bps); // Set output data c->audio = l->audio; c->len = len*l->bps; c->bps = l->bps; c->format = l->format; return c; }