static void get_sample_data (Priv *p, long sample_no, float *left, float *right) { int to_remove = 0; GList *l; if (sample_no < 0) return; for (l = p->audio_track; l; l = l->next) { GeglAudioFragment *af = l->data; int channels = gegl_audio_fragment_get_channels (af); int pos = gegl_audio_fragment_get_pos (af); int sample_count = gegl_audio_fragment_get_sample_count (af); if (sample_no > pos + sample_count) { to_remove ++; } if (pos <= sample_no && sample_no < pos + sample_count) { int i = sample_no - pos; *left = af->data[0][i]; if (channels == 1) *right = af->data[0][i]; else *right = af->data[1][i]; if (to_remove) /* consuming audiotrack */ { again: for (l = p->audio_track; l; l = l->next) { GeglAudioFragment *af = l->data; int pos = gegl_audio_fragment_get_pos (af); int sample_count = gegl_audio_fragment_get_sample_count (af); if (sample_no > pos + sample_count) { p->audio_track = g_list_remove (p->audio_track, af); g_object_unref (af); goto again; } } } return; } } *left = 0; *right = 0; }
static int extract_audio_energy (GeglAudioFragment *audio, uint8_t *audio_energy, int dups) { int i; float left_max = 0; float right_max = 0; float left_sum = 0; float right_sum = 0; int sample_count = gegl_audio_fragment_get_sample_count (audio); for (i = 0; i < sample_count; i++) { left_sum += fabs (audio->data[0][i]); right_sum += fabs (audio->data[1][i]); if (fabs (audio->data[0][i]) > left_max) left_max = fabs (audio->data[0][i]); if (fabs (audio->data[1][i]) > right_max) right_max = fabs (audio->data[1][i]); } left_sum /= sample_count; right_sum /= sample_count; left_max = left_sum; right_max = right_sum; left_max *= 255; if (left_max > 255) left_max = 255; right_max *= 255; if (right_max > 255) right_max = 255; for (i = 0; i < dups; i ++) { audio_energy[3*i+0] = left_max; audio_energy[3*i+1] = (left_max+right_max)/2; audio_energy[3*i+2] = right_max; } return 3 * dups; }
void write_audio_frame (GeglProperties *o, AVFormatContext * oc, AVStream * st) { Priv *p = (Priv*)o->user_data; AVCodecContext *c = st->codec; int sample_count = 100000; static AVPacket pkt = { 0 }; if (pkt.size == 0) { av_init_packet (&pkt); } /* first we add incoming frames audio samples */ { int i; int sample_count = gegl_audio_fragment_get_sample_count (o->audio); GeglAudioFragment *af = gegl_audio_fragment_new (gegl_audio_fragment_get_sample_rate (o->audio), gegl_audio_fragment_get_channels (o->audio), gegl_audio_fragment_get_channel_layout (o->audio), sample_count); gegl_audio_fragment_set_sample_count (af, sample_count); for (i = 0; i < sample_count; i++) { af->data[0][i] = o->audio->data[0][i]; af->data[1][i] = o->audio->data[1][i]; } gegl_audio_fragment_set_pos (af, p->audio_pos); p->audio_pos += sample_count; p->audio_track = g_list_append (p->audio_track, af); } if (!(c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) sample_count = c->frame_size; /* then we encode as much as we can in a loop using the codec frame size */ while (p->audio_pos - p->audio_read_pos > sample_count) { long i; int ret; int got_packet = 0; AVFrame *frame = alloc_audio_frame (c->sample_fmt, c->channel_layout, c->sample_rate, sample_count); switch (c->sample_fmt) { case AV_SAMPLE_FMT_FLT: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((float*)frame->data[0])[c->channels*i+0] = left; ((float*)frame->data[0])[c->channels*i+1] = right; } break; case AV_SAMPLE_FMT_FLTP: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((float*)frame->data[0])[i] = left; ((float*)frame->data[1])[i] = right; } break; case AV_SAMPLE_FMT_S16: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int16_t*)frame->data[0])[c->channels*i+0] = left * (1<<15); ((int16_t*)frame->data[0])[c->channels*i+1] = right * (1<<15); } break; case AV_SAMPLE_FMT_S32: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int32_t*)frame->data[0])[c->channels*i+0] = left * (1<<31); ((int32_t*)frame->data[0])[c->channels*i+1] = right * (1<<31); } break; case AV_SAMPLE_FMT_S32P: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int32_t*)frame->data[0])[i] = left * (1<<31); ((int32_t*)frame->data[1])[i] = right * (1<<31); } break; case AV_SAMPLE_FMT_S16P: for (i = 0; i < sample_count; i++) { float left = 0, right = 0; get_sample_data (p, i + p->audio_read_pos, &left, &right); ((int16_t*)frame->data[0])[i] = left * (1<<15); ((int16_t*)frame->data[1])[i] = right * (1<<15); } break; default: fprintf (stderr, "eeeek unhandled audio format\n"); break; } frame->pts = p->next_apts; p->next_apts += sample_count; av_frame_make_writable (frame); ret = avcodec_encode_audio2 (c, &pkt, frame, &got_packet); av_packet_rescale_ts (&pkt, st->codec->time_base, st->time_base); if (ret < 0) { fprintf (stderr, "Error encoding audio frame: %s\n", av_err2str (ret)); } if (got_packet) { pkt.stream_index = st->index; av_interleaved_write_frame (oc, &pkt); av_free_packet (&pkt); } av_frame_free (&frame); p->audio_read_pos += sample_count; } }