5
5
# it under the terms of the GNU General Public License version 3, as
6
6
# published by the Free Software Foundation
8
#http://xiph.org/vorbis/doc/framing.html
9
#http://xiph.org/vorbis/doc/v-comment.html
8
# https://xiph.org/ogg/doc/framing.html
9
# https://xiph.org/vorbis/doc/v-comment.html
11
11
# https://tools.ietf.org/html/rfc7845.html
12
12
# https://wiki.xiph.org/OggOpus
155
155
# calculate bitrate, excluding the metadata packet
156
156
my $audiosize= (-s $file) - $self->{commentpack_size};
157
$self->{info}{bitrate_calculated}= 8*$audiosize / $self->{info}{seconds};
157
$self->{info}{bitrate_calculated}= 8*$audiosize / $self->{info}{seconds} if $self->{info}{seconds};
203
203
{ my $self=shift;
204
204
my $newcom_packref=_PackComments($self);
205
205
#warn "old size $self->{commentpack_size}, need : ".length($$newcom_packref)."\n";
206
# 1. if enough room: write in-place
207
if ( $self->{commentpack_size} >= length $$newcom_packref)
206
# case 1. if enough room and not too much room: write in-place
207
my $enough= $self->{commentpack_size} - length $$newcom_packref;
208
if ($enough>=0 && $enough<2048)
208
209
{ warn "in place editing.\n";
209
210
my $left=length $$newcom_packref;
211
212
my $fh=$self->_openw or return;
212
_read_packet($self,PACKET_INFO); #skip first page
216
unless (_read_packet($self,PACKET_INFO)) #skip first page
217
{ $error="Can't find info packet"; $left=0;
219
my $startwrite= tell $fh;
220
# read previous comments pages, replace the comments
215
my ($pageref,$offset,$size)=_ReadPage($self);
217
if ($left<$size) {$size=$left; $left=0;}
219
substr $$pageref,$offset,$size,substr($$newcom_packref,$offset2,$size);
221
_recompute_page_crc($pageref);
222
print $fh $$pageref or warn $!;
222
{ my ($pageref,$offset,$size)=_ReadPage($self);
223
unless ($pageref) { $error="error reading comment page"; last; }
224
if ($left<$size) {$size=$left; $left=0;}
226
substr $$pageref,$offset,$size,substr($$newcom_packref,$offset2,$size);
228
_recompute_page_crc($pageref);
229
$towrite.= $$pageref;
232
seek $fh,$startwrite,0;
233
unless ($error) { print $fh $towrite or $error=$!; }
236
{ warn "oggheader: error writing tag in $self->{filename}: $error\n";
228
# 2. if not enough room: create new file and replace old file
242
# case 2. if not enough room: create new file and replace old file
229
243
my $INfh=$self->_open or return;
230
244
my $OUTfh=$self->_openw(1) or return; #open .TEMP file
271
285
#warn unpack('C*',$segments),"\n";
272
286
#warn "$size ",length($data)-$data_offset,"\n";
273
287
warn "writing page $pagenb\n" if $::debug;
274
my $page=pack('a4aa x8 a4 V x4 C','OggS',$version,$continued,$serial,$pagenb++,$nbseg).$segments.substr($data,$data_offset,$size);
288
my $granule= $seg==255 ? "\xff"x8 : "\x00"x8; # 0 if packet ends on this page, -1 if not
289
my $page=pack('a4aa a8 a4 V x4 C','OggS',$version,$continued,$granule,$serial,$pagenb++,$nbseg).$segments.substr($data,$data_offset,$size);
275
290
_recompute_page_crc(\$page);
276
291
print $OUTfh $page or warn $!;
277
292
$data_offset+=$size;
285
300
my $pos=tell $INfh; read $INfh,$data,27; seek $INfh,$pos,0;
286
301
#warn "first audio data on page ".unpack('x18V',$data)."\n";
287
302
# fast raw copy by 1M chunks if page numbers haven't changed
288
if ( substr($data,0,4) eq 'OggS' && unpack('x18V',$data) eq $pagenb)
290
print $OUTfh $buffer or warn $! while read $INfh,$buffer,1048576;
303
if (substr($data,0,4) eq 'OggS' && unpack('x18V',$data) == $pagenb)
305
print $OUTfh $buffer or warn $! while read $INfh,$buffer,1048576;
293
308
# __SLOW__ copy if page number must be changed -> and crc recomputed
298
313
_recompute_page_crc($pageref); #recompute crc
299
314
print $OUTfh $$pageref or warn $!; #write page
316
# if we didn't reach end of file, something went wrong, abort
317
unless (eof($self->{fileHandle}))
318
{ warn "oggheader: error reading pages of $self->{filename} while copying audio data, aborting write\n";
321
unlink $self->{filename}.'.TEMP';
322
%$self=(); #destroy the object to make sure it is not reused as many of its data are now invalid
547
571
my $r=read $fh,$buf,27;
548
572
return 0 unless $r==27;
549
#http://www.xiph.org/ogg/vorbis/doc/framing.html
573
# https://xiph.org/ogg/doc/framing.html
550
574
# 'OggS' 4 bytes capture_pattern 0
551
575
# 0x00 1 byte stream_structure_version 1
552
576
# 1 byte header_type_flag 2