void OggOpusFile::WriteHeader() { /*The Identification Header is 19 bytes, plus a Channel Mapping Table for mapping families other than 0. The Channel Mapping Table is 2 bytes + 1 byte per channel. Because the maximum number of channels is 255, the maximum size of this header is 19 + 2 + 255 = 276 bytes.*/ unsigned char header_data[276]; const char *opus_version; opus_version=opus_get_version_string(); comment_init(&inopt.comments, &inopt.comments_length, opus_version); // snprintf(ENCODER_string, sizeof(ENCODER_string), "opusenc from %s %s",PACKAGE_NAME,"1.5"); CStdString encode_string; encode_string.Format("opusenc from %s 1.5", PACKAGE_NAME); strcpy(ENCODER_string, encode_string.c_str()); comment_add(&inopt.comments, &inopt.comments_length, "ENCODER", ENCODER_string); int packet_size=opus_header_to_packet(&header, header_data, sizeof(header_data)); op.packet=header_data; op.bytes=packet_size; op.b_o_s=1; op.e_o_s=0; op.granulepos=0; op.packetno=0; ogg_stream_packetin(&os, &op); while((ret=ogg_stream_flush(&os, &og))){ if(!ret)break; ret=oe_write_page(&og); if(ret!=og.header_len+og.body_len){ fprintf(stderr,"Error: failed writing header to output stream\n"); exit(1); } bytes_written+=ret; pages_out++; } comment_pad(&inopt.comments, &inopt.comments_length, comment_padding); op.packet=(unsigned char *)inopt.comments; op.bytes=inopt.comments_length; op.b_o_s=0; op.e_o_s=0; op.granulepos=0; op.packetno=1; ogg_stream_packetin(&os, &op); /* writing the rest of the Opus header packets */ while((ret=ogg_stream_flush(&os, &og))){ if(!ret)break; ret=oe_write_page(&og); if(ret!=og.header_len + og.body_len){ fprintf(stderr,"Error: failed writing header to output stream\n"); exit(1); } bytes_written+=ret; pages_out++; } }
int opus_write_header(uint8_t **p_extra, int *i_extra, OpusHeader *header) { unsigned char header_data[100]; const int packet_size = opus_header_to_packet(header, header_data, sizeof(header_data)); ogg_packet headers[2]; headers[0].packet = header_data; headers[0].bytes = packet_size; headers[0].b_o_s = 1; headers[0].e_o_s = 0; headers[0].granulepos = 0; headers[0].packetno = 0; size_t comments_length; char *comments = comment_init(&comments_length); if (!comments) return 1; if (comment_add(&comments, &comments_length, "ENCODER=", "VLC media player")) { free(comments); return 1; } if (comment_pad(&comments, &comments_length)) { free(comments); return 1; } headers[1].packet = (unsigned char *) comments; headers[1].bytes = comments_length; headers[1].b_o_s = 0; headers[1].e_o_s = 0; headers[1].granulepos = 0; headers[1].packetno = 1; for (unsigned i = 0; i < ARRAY_SIZE(headers); ++i) { if (xiph_AppendHeaders(i_extra, (void **) p_extra, headers[i].bytes, headers[i].packet)) { *i_extra = 0; *p_extra = NULL; } } return 0; }
int opus_write_header(uint8_t **p_extra, int *i_extra, OpusHeader *header, const char *vendor) { unsigned char header_data[100]; const int packet_size = opus_header_to_packet(header, header_data, sizeof(header_data)); unsigned char *data[2]; size_t size[2]; data[0] = header_data; size[0] = packet_size; size_t comments_length; char *comments = comment_init(&comments_length, vendor); if (!comments) return 1; if (comment_add(&comments, &comments_length, "ENCODER=", "VLC media player")) { free(comments); return 1; } if (comment_pad(&comments, &comments_length)) { free(comments); return 1; } data[1] = (unsigned char *) comments; size[1] = comments_length; for (unsigned i = 0; i < ARRAY_SIZE(data); ++i) if (xiph_AppendHeaders(i_extra, (void **) p_extra, size[i], data[i])) { *i_extra = 0; *p_extra = NULL; } return 0; }
int initRecorder(const char *path) { cleanupRecorder(); if (!path) { return 0; } _fileOs = fopen(path, "wb"); if (!_fileOs) { return 0; } inopt.rate = rate; inopt.gain = 0; inopt.endianness = 0; inopt.copy_comments = 0; inopt.rawmode = 1; inopt.ignorelength = 1; inopt.samplesize = 16; inopt.channels = 1; inopt.skip = 0; comment_init(&inopt.comments, &inopt.comments_length, opus_get_version_string()); if (rate > 24000) { coding_rate = 48000; } else if (rate > 16000) { coding_rate = 24000; } else if (rate > 12000) { coding_rate = 16000; } else if (rate > 8000) { coding_rate = 12000; } else { coding_rate = 8000; } if (rate != coding_rate) { LOGE("Invalid rate"); return 0; } header.channels = 1; header.channel_mapping = 0; header.input_sample_rate = rate; header.gain = inopt.gain; header.nb_streams = 1; int result = OPUS_OK; _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_AUDIO, &result); if (result != OPUS_OK) { LOGE("Error cannot create encoder: %s", opus_strerror(result)); return 0; } min_bytes = max_frame_bytes = (1275 * 3 + 7) * header.nb_streams; _packet = malloc(max_frame_bytes); result = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate)); if (result != OPUS_OK) { LOGE("Error OPUS_SET_BITRATE returned: %s", opus_strerror(result)); return 0; } #ifdef OPUS_SET_LSB_DEPTH result = opus_encoder_ctl(_encoder, OPUS_SET_LSB_DEPTH(max(8, min(24, inopt.samplesize)))); if (result != OPUS_OK) { LOGE("Warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(result)); } #endif opus_int32 lookahead; result = opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&lookahead)); if (result != OPUS_OK) { LOGE("Error OPUS_GET_LOOKAHEAD returned: %s", opus_strerror(result)); return 0; } inopt.skip += lookahead; header.preskip = (int)(inopt.skip * (48000.0 / coding_rate)); inopt.extraout = (int)(header.preskip * (rate / 48000.0)); if (ogg_stream_init(&os, rand()) == -1) { LOGE("Error: stream init failed"); return 0; } unsigned char header_data[100]; int packet_size = opus_header_to_packet(&header, header_data, 100); op.packet = header_data; op.bytes = packet_size; op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = 0; ogg_stream_packetin(&os, &op); while ((result = ogg_stream_flush(&os, &og))) { if (!result) { break; } int pageBytesWritten = writeOggPage(&og, _fileOs); if (pageBytesWritten != og.header_len + og.body_len) { LOGE("Error: failed writing header to output stream"); return 0; } bytes_written += pageBytesWritten; pages_out++; } comment_pad(&inopt.comments, &inopt.comments_length, comment_padding); op.packet = (unsigned char *)inopt.comments; op.bytes = inopt.comments_length; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = 1; ogg_stream_packetin(&os, &op); while ((result = ogg_stream_flush(&os, &og))) { if (result == 0) { break; } int writtenPageBytes = writeOggPage(&og, _fileOs); if (writtenPageBytes != og.header_len + og.body_len) { LOGE("Error: failed writing header to output stream"); return 0; } bytes_written += writtenPageBytes; pages_out++; } free(inopt.comments); return 1; }