[xiph-cvs] cvs commit: vorbis-tools/vcut vcut.c vcut.h
Michael Smith
msmith at xiph.org
Sat Mar 24 06:12:36 PST 2001
msmith 01/03/24 06:12:36
Added: vcut vcut.c vcut.h
Log:
First (well, second) almost-working version of vcut.
No build stuff.
Massive memory leaks.
Doesn't quite work.
Messy code.
Full of annoying debug stuff.
Several chunks need a complete rewrite.
Not recommended for the faint of heart.
Revision Changes Path
1.1 vorbis-tools/vcut/vcut.c
Index: vcut.c
===================================================================
/* This program is licensed under the GNU General Public License, version 2,
* a copy of which is included with this program.
*
* (c) 2000-2001 Michael Smith <msmith at labyrinth.net.au>
*
*
* Simple application to cut an ogg at a specified frame, and produce two
* output files.
*
* last modified: $Id: vcut.c,v 1.1 2001/03/24 14:12:35 msmith Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include <time.h>
#include <errno.h>
#include <string.h>
/* Erk. We need some internal headers too (at the moment, anyway) */
#include "lib/codec_internal.h"
#include "lib/misc.h"
#include "vcut.h"
int main(int argc, char **argv)
{
ogg_int64_t cutpoint;
FILE *in,*out1,*out2;
if(argc<5)
{
fprintf(stderr,
"Usage: vcut infile.ogg outfile1.ogg outfile2.ogg cutpoint\n");
exit(1);
}
in = fopen(argv[1], "rb");
if(!in) {
fprintf(stderr, "Couldn't open %s for reading\n", argv[1]);
exit(1);
}
out1 = fopen(argv[2], "wb");
if(!out1) {
fprintf(stderr, "Couldn't open %s for writing\n", argv[2]);
exit(1);
}
out2 = fopen(argv[3], "wb");
if(!out2) {
fprintf(stderr, "Couldn't open %s for writing\n", argv[3]);
exit(1);
}
sscanf(argv[4], "%Ld", &cutpoint);
if(vcut_process(in,out1,out2,cutpoint))
{
fprintf(stderr, "Processing failed\n");
exit(1);
}
fclose(in);
fclose(out1);
fclose(out2);
return 0;
}
int vcut_process(FILE *in, FILE *first, FILE *second, ogg_int64_t cutpoint)
{
ogg_stream_state stream_out_first;
ogg_stream_state stream_out_second;
vcut_state *s;
s = vcut_new_state();
fprintf(stderr, "Processing: Cutting at %lld\n", cutpoint);
s->cutpoint = cutpoint;
/* Read headers in, and save them */
vcut_process_headers(s, in);
/* ok, headers are all in, and saved */
fprintf(stderr, "Header reading complete\n");
vorbis_synthesis_init(s->vd,s->vi);
vorbis_block_init(s->vd,s->vb);
ogg_stream_init(&stream_out_first, s->serial); /* first file gets original */
srand(time(NULL));
ogg_stream_init(&stream_out_second, rand()); /* second gets random */
vcut_submit_headers_to_stream(&stream_out_first, s);
vcut_submit_headers_to_stream(&stream_out_second, s);
vcut_flush_pages_to_file(&stream_out_first, first);
vcut_flush_pages_to_file(&stream_out_second, second);
vcut_process_first_stream(s, &stream_out_first, in, first);
ogg_stream_clear(&stream_out_first);
vcut_process_second_stream(s, &stream_out_second, in, second);
ogg_stream_clear(&stream_out_second);
/* Free some memory! */
return 0;
}
vcut_state *vcut_new_state()
{
vcut_state *s = malloc(sizeof(vcut_state));
memset(s,0,sizeof(vcut_state));
s->sync_in = malloc(sizeof(ogg_sync_state));
s->stream_in = malloc(sizeof(ogg_stream_state));
s->vd = malloc(sizeof(vorbis_dsp_state));
s->vi = malloc(sizeof(vorbis_info));
s->vb = malloc(sizeof(vorbis_block));
return s;
}
void vcut_process_first_stream(vcut_state *s, ogg_stream_state *stream, FILE *in, FILE *f)
{
int eos=0;
ogg_page page;
ogg_packet packet;
ogg_int64_t granpos, prevgranpos;
int result;
while(!eos)
{
while(!eos)
{
int result = ogg_sync_pageout(s->sync_in, &page);
if(result==0) break;
else if(result<0) fprintf(stderr, "Page error. May not work\n");
else
{
granpos = ogg_page_granulepos(&page);
fprintf(stderr, "Input page: %lld\n", granpos);
ogg_stream_pagein(s->stream_in, &page);
fprintf(stderr, "granpos: %lld, cutpoint; %lld\n", granpos, s->cutpoint);
if(granpos < s->cutpoint)
{
while(1)
{
result=ogg_stream_packetout(s->stream_in, &packet);
/* throw away result */
vcut_get_blocksize(s,s->vb,&packet);
if(result==0) break;
else if(result==-1)
fprintf(stderr, "Bitstream error, continuing\n");
else
{
/* Free these somewhere: FIXME!!! */
s->packets[0] = vcut_save_packet(&packet);
// Count pcm??
ogg_stream_packetin(stream, &packet);
vcut_write_pages_to_file(stream, f);
}
}
prevgranpos = granpos;
}
else
{
fprintf(stderr, "Page passes cutpoint\n");
eos=1; /* This way we break out */
}
if(ogg_page_eos(&page))
{
fprintf(stderr, "Found EOS page\n");
eos=1;
}
}
}
if(!eos)
{
if(vcut_update_sync(s,in)==0)
{
fprintf(stderr, "Setting eos: update sync returned 0\n");
eos=1;
}
}
}
while((result = ogg_stream_packetout(s->stream_in, &packet))!=0)
{
int bs = vcut_get_blocksize(s, s->vb, &packet);
prevgranpos += bs;
fprintf(stderr, "prevgranpos += %d -> %lld\n", bs, prevgranpos);
if(prevgranpos > s->cutpoint)
{
fprintf(stderr, "Passed cutpoint: %lld\n", s->cutpoint);
s->packets[1] = vcut_save_packet(&packet);
packet.granulepos = s->cutpoint; /* Set it! */
packet.e_o_s = 1;
ogg_stream_packetin(stream, &packet);
break;
}
/* Free these? */
s->packets[0] = vcut_save_packet(&packet);
ogg_stream_packetin(stream, &packet);
vcut_write_pages_to_file(stream,f);
}
vcut_write_pages_to_file(stream,f);
/* Remaining samples in first packet */
s->initialgranpos = prevgranpos - s->cutpoint;
fprintf(stderr, "Trimming %lld samples from end of first stream (placing on second stream\n", s->initialgranpos);
fprintf(stderr, "Completed first stream!\n");
}
void vcut_process_second_stream(vcut_state *s, ogg_stream_state *stream, FILE *in, FILE *f)
{
ogg_packet packet;
ogg_page page;
int eos=0;
int result;
ogg_int64_t page_granpos, current_granpos=s->initialgranpos;
ogg_int64_t packetnum=0; /* Do we even care? */
packet.bytes = s->packets[0]->length;
packet.packet = s->packets[0]->packet;
packet.b_o_s = 0;
packet.e_o_s = 0;
packet.granulepos = 0;
packet.packetno = packetnum++; /* 0 or 3 for the first audio packet? */
ogg_stream_packetin(stream,&packet);
packet.bytes = s->packets[1]->length;
packet.packet = s->packets[1]->packet;
packet.b_o_s = 0;
packet.e_o_s = 0;
packet.granulepos = s->initialgranpos;
packet.packetno = packetnum++;
ogg_stream_packetin(stream,&packet);
while(ogg_stream_flush(stream, &page)!=0)
{
fprintf(stderr, "Flushing (should be only one page)\n");
fwrite(page.header,1,page.header_len,f);
fwrite(page.body,1,page.body_len,f);
}
while(!eos)
{
while(!eos)
{
result=ogg_sync_pageout(s->sync_in, &page);
if(result==0) break;
else if(result==-1)
fprintf(stderr, "Recoverable bitstream error\n");
else
{
page_granpos = ogg_page_granulepos(&page) - s->cutpoint;
if(ogg_page_eos(&page))eos=1;
ogg_stream_pagein(s->stream_in, &page);
while(1)
{
result = ogg_stream_packetout(s->stream_in, &packet);
if(result==0) break;
else if(result==-1) fprintf(stderr, "Bitstream error\n");
else
{
int bs = vcut_get_blocksize(s, s->vb, &packet);
current_granpos += bs;
if(current_granpos > page_granpos)
{
fprintf(stderr, "INFO: Truncating at granpos=%lld->%lld\n", current_granpos, page_granpos);
current_granpos = page_granpos;
}
packet.granulepos = current_granpos;
packet.packetno = packetnum++;
ogg_stream_packetin(stream, &packet);
vcut_write_pages_to_file(stream,f);
}
}
}
}
if(!eos)
{
if(vcut_update_sync(s, in)==0)
{
fprintf(stderr, "Update sync returned 0, setting eos\n");
eos=1;
}
}
}
}
long vcut_get_blocksize(vcut_state *s, vorbis_block *vb, ogg_packet *op)
{
vorbis_info *vi = vb->vd->vi;
oggpack_buffer *opb = &vb->opb;
int mode;
codec_setup_info *ci = vi->codec_setup;
int ret;
oggpack_readinit(opb,op->packet, op->bytes);
if(oggpack_read(opb,1)!=0) return 0;
mode = oggpack_read(opb,
((backend_lookup_state *)vb->vd->backend_state)->modebits);
ret = (ci->blocksizes[ci->mode_param[mode]->blockflag] +
ci->blocksizes[s->prevW])/4;
/* remember to init prevW to appropriate thing */
s->prevW = ci->mode_param[mode]->blockflag;
return ret;
}
int vcut_update_sync(vcut_state *s, FILE *f)
{
unsigned char *buffer = ogg_sync_buffer(s->sync_in, 4096);
int bytes = fread(buffer,1,4096,f);
ogg_sync_wrote(s->sync_in, bytes);
return bytes;
}
void vcut_submit_headers_to_stream(ogg_stream_state *stream, vcut_state *s)
{
int i;
for(i=0;i<3;i++)
{
ogg_packet p;
p.bytes = s->headers[i]->length;
p.packet = s->headers[i]->packet;
p.b_o_s = ((i==0)?1:0);
p.e_o_s = 0;
p.granulepos=0;
ogg_stream_packetin(stream, &p);
}
}
void vcut_process_headers(vcut_state *s, FILE *in)
{
vorbis_comment vc;
ogg_page page;
ogg_packet packet;
int bytes;
int i;
unsigned char *buffer;
ogg_sync_init(s->sync_in);
vorbis_info_init(s->vi);
vorbis_comment_init(&vc);
buffer = ogg_sync_buffer(s->sync_in, 4096);
bytes = fread(buffer, 1, 4096, in);
ogg_sync_wrote(s->sync_in, bytes);
if(ogg_sync_pageout(s->sync_in, &page)!=1){
fprintf(stderr, "Input not ogg.\n");
exit(1);
}
s->serial = ogg_page_serialno(&page);
ogg_stream_init(s->stream_in, s->serial);
if(ogg_stream_pagein(s->stream_in, &page) <0)
{
fprintf(stderr, "Error in first page\n");
exit(1);
}
if(ogg_stream_packetout(s->stream_in, &packet)!=1){
fprintf(stderr, "error in first packet\n");
exit(1);
}
if(vorbis_synthesis_headerin(s->vi, &vc, &packet)<0)
{
fprintf(stderr, "Error in primary header: not vorbis?\n");
exit(1);
}
fprintf(stderr, "headerin: read primary header\n");
s->headers[0] = vcut_save_packet(&packet);
i=0;
while(i<2)
{
while(i<2) {
int res = ogg_sync_pageout(s->sync_in, &page);
if(res==0)break;
if(res==1)
{
ogg_stream_pagein(s->stream_in, &page);
while(i<2)
{
res = ogg_stream_packetout(s->stream_in, &packet);
if(res==0)break;
if(res<0){
fprintf(stderr, "Secondary header corrupt\n");
exit(1);
}
s->headers[i+1] = vcut_save_packet(&packet);
vorbis_synthesis_headerin(s->vi,&vc,&packet);
i++;
}
}
}
buffer=ogg_sync_buffer(s->sync_in, 4096);
bytes=fread(buffer,1,4096,in);
if(bytes==0 && i<2)
{
fprintf(stderr, "EOF in headers\n");
exit(1);
}
ogg_sync_wrote(s->sync_in, bytes);
}
}
vcut_packet *vcut_save_packet(ogg_packet *packet)
{
vcut_packet *p = malloc(sizeof(vcut_packet));
p->length = packet->bytes;
p->packet = malloc(p->length);
memcpy(p->packet, packet->packet, p->length);
return p;
}
void vcut_write_pages_to_file(ogg_stream_state *stream, FILE *file)
{
ogg_page page;
while(ogg_stream_pageout(stream, &page))
{
fwrite(page.header,1,page.header_len, file);
fwrite(page.body,1,page.body_len, file);
}
}
void vcut_flush_pages_to_file(ogg_stream_state *stream, FILE *file)
{
ogg_page page;
while(ogg_stream_flush(stream, &page))
{
fwrite(page.header,1,page.header_len, file);
fwrite(page.body,1,page.body_len, file);
}
}
1.1 vorbis-tools/vcut/vcut.h
Index: vcut.h
===================================================================
#ifndef __VCUT_H
#define __VCUT_H
#include <stdio.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>
typedef struct {
int length;
unsigned char *packet;
} vcut_packet;
typedef struct {
ogg_sync_state *sync_in;
ogg_stream_state *stream_in;
vorbis_dsp_state *vd;
vorbis_block *vb;
vorbis_info *vi;
int prevW;
ogg_int64_t initialgranpos;
ogg_int64_t cutpoint;
unsigned int serial;
vcut_packet *headers[3];
vcut_packet *packets[2];
} vcut_state;
int vcut_process(FILE *in, FILE *first, FILE *second, ogg_int64_t cutpoint);
long vcut_blocksize(vorbis_block *vb, ogg_packet *op);
vcut_packet *vcut_save_packet(ogg_packet *packet);
void vcut_submit_headers_to_stream(ogg_stream_state *stream, vcut_state *s);
void vcut_process_headers(vcut_state *s, FILE *in);
void vcut_write_pages_to_file(ogg_stream_state *stream, FILE *file);
void vcut_flush_pages_to_file(ogg_stream_state *stream, FILE *file);
int vcut_update_sync(vcut_state *s, FILE *f);
vcut_state *vcut_new_state(void);
void vcut_process_first_stream(vcut_state *s, ogg_stream_state *stream, FILE *in, FILE *f);
void vcut_process_second_stream(vcut_state *s, ogg_stream_state *stream, FILE *in,FILE *f);
long vcut_get_blocksize(vcut_state *s, vorbis_block *vb, ogg_packet *p);
#endif /* __VCUT_H */
--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list