add schro_decode option to write one file per output frame
[schroedinger-tools.git] / src / schro_decode.cpp
blob41bcacfb3cbae81511f512c833d5ed7a5dcd775a
1 /* Schrodinger decoder wrapper to for non GStreamer applications
2 * derived from gstschrodec.c & testsuite/decode.c
3 * 2006 Jon Rosser BBC R&D
5 */
7 #include <iostream>
8 #include <string>
10 #include <stdio.h>
11 #include <cstdio>
12 #include <string.h>
13 #include <errno.h>
15 #include <schroedinger/schro.h>
16 #include <schroedinger/schroparams.h>
18 #include <boost/program_options.hpp>
19 namespace po = boost::program_options;
21 #include "common.h"
22 #include "parse.h"
24 /* global variables */
25 static std::string inFileName;
26 static std::string outFileName;
27 static bool verbose = false;
28 static bool split = false;
30 /* function prototypes */
31 static bool parseCommandLine(int argc, char *argv[]);
32 static void decode();
34 int main(int argc, char **argv)
37 schro_init();
39 if(parseCommandLine(argc, argv)) {
40 exit(1);
43 decode();
45 return 0;
48 bool parseCommandLine(int argc, char **argv)
50 bool ret=false;
52 try {
54 //Video format options
55 po::options_description desc("Allowed Options");
56 desc.add_options()
57 ("help", " Show this message")
58 ("verbose,v", " Enable verbose decoding")
59 ("split,s", " Split output into frames [put %d in filename]")
60 ("input", po::value(&inFileName), "string Dirac bitstream to decode")
61 ("output", po::value(&outFileName), "string YUV planar output file");
63 //the filenames are 'positional options'
64 po::positional_options_description p;
65 p.add("input", 1);
66 p.add("output", 2);
68 //do the command line parsing
69 po::variables_map vm;
70 po::store(po::command_line_parser(argc, argv). options(desc).positional(p).run(), vm);
71 po::notify(vm);
73 //decode flags
74 if(vm.count("verbose")) verbose=true;
75 if(vm.count("split")) split=true;
76 if(vm.count("help")) {
77 std::cout << "Usage : schro_decode [flags] input output" << std::endl;
78 std::cout << desc << std::endl;
79 ret = true;
82 if(vm.count("input") == 0)
83 throw(std::runtime_error("No input file specified"));
85 if(vm.count("output") == 0)
86 throw(std::runtime_error("No output file specified"));
89 catch(std::exception& e)
91 printf("Command line error : ");
92 std::cout << e.what() << "\n";
93 ret = true;
96 return ret;
99 static void
100 buffer_free (SchroBuffer *buf, void *priv)
102 free (priv);
105 /* push the data through the decoder */
106 static void decode()
108 FILE *infile;
109 FILE *outfile = NULL;
111 SchroDecoder *decoder;
112 SchroBuffer *buffer;
113 SchroVideoFormat *format = NULL;
114 SchroFrame *frame;
115 bool go;
116 void *packet;
117 int size=-1;
118 int it;
119 int ret;
120 int framecount=0;
121 char formatted_name[1024];
123 /* open an input and output files */
124 infile = fopen(inFileName.c_str(), "rb");
125 if(infile == NULL) {
126 fprintf(stderr, "Could not open input file %s\n", inFileName.c_str());
127 exit(1);
130 decoder = schro_decoder_new();
132 while(true) {
134 //on the previous iteration feof(inFile) = true, so stop
135 if(size == 0)
136 goto out;
138 //get a packet from the stream and push it to the decoder
139 ret = parse_packet (infile, &packet, &size);
141 if(ret == PARSE_ERROR)
142 goto out;
144 if (size == 0) {
145 //unexpected end of file from parser
146 schro_decoder_push_end_of_stream (decoder);
147 } else {
148 buffer = schro_buffer_new_with_data (packet, size);
149 buffer->free = buffer_free;
150 buffer->priv = packet;
152 it = schro_decoder_push (decoder, buffer);
153 if (it == SCHRO_DECODER_FIRST_ACCESS_UNIT) {
154 format = schro_decoder_get_video_format (decoder);
155 if(verbose) {
156 printf("\nFirst Sequence Header:\n");
157 showVideoFormat(format);
162 //iterate the decoder until it needs more data
163 go = true;
164 while (go == true) {
165 it = schro_decoder_wait (decoder);
167 switch (it) {
168 case SCHRO_DECODER_NEED_BITS:
169 go = false;
170 break;
171 case SCHRO_DECODER_NEED_FRAME:
172 switch(format->chroma_format) {
173 case SCHRO_CHROMA_444:
174 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_444,
175 format->width, format->height);
176 break;
177 case SCHRO_CHROMA_422:
178 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_422,
179 format->width, format->height);
180 break;
181 case SCHRO_CHROMA_420:
182 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_420,
183 format->width, format->height);
184 break;
185 default:
186 printf("error: unrecognised chroma format\n");
187 exit(1);
188 break;
190 schro_decoder_add_output_picture (decoder, frame);
191 break;
192 case SCHRO_DECODER_OK:
194 frame = schro_decoder_pull (decoder);
196 if(split == true || outfile == NULL) {
197 snprintf(formatted_name, 64, outFileName.c_str(), framecount);
199 outfile = fopen(formatted_name, "wb");
200 if(outfile == NULL) {
201 fprintf(stderr, "Could not open output file %s\n", formatted_name);
202 exit(1);
206 if(verbose) {
207 printf("writing output frame %d to %s\r", framecount, formatted_name);
208 fflush(stdout);
211 // write frame data out in planar format
212 fwrite(frame->components[0].data, frame->components[0].length, 1, outfile);
213 fwrite(frame->components[1].data, frame->components[1].length, 1, outfile);
214 fwrite(frame->components[2].data, frame->components[2].length, 1, outfile);
215 schro_frame_unref(frame);
217 if(split) fclose(outfile);
219 framecount++;
221 break;
222 case SCHRO_DECODER_EOS:
223 if(verbose) printf("\nGot End of Sequence");
224 schro_decoder_reset(decoder);
225 go = false;
226 break;
227 case SCHRO_DECODER_ERROR:
228 printf("\nerror: got decoder internal error - exiting\n");
229 goto out;
230 break;
235 out:
237 if(verbose) printf("\nFreeing decoder");
238 schro_decoder_free (decoder);
239 free(format);
241 fclose(infile);
242 fclose(outfile);