introduce enumerated return codes from parse_packet
[schroedinger-tools.git] / src / schro_decode.cpp
blobcda781512b3d63d94df7aadaa40abe4599ff90b7
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 <string.h>
12 #include <errno.h>
14 #include <schroedinger/schro.h>
15 #include <schroedinger/schroparams.h>
17 #include <boost/program_options.hpp>
18 namespace po = boost::program_options;
20 #include "common.h"
21 #include "parse.h"
23 /* global variables */
24 static std::string inFileName;
25 static std::string outFileName;
26 static bool verbose = false;
28 /* function prototypes */
29 static bool parseCommandLine(int argc, char *argv[]);
30 static void decode(FILE*, FILE*);
32 int main(int argc, char **argv)
34 FILE *inFile;
35 FILE *outFile;
37 schro_init();
39 if(parseCommandLine(argc, argv)) {
40 exit(1);
43 /* open an input and output files */
44 inFile = fopen(inFileName.c_str(), "rb");
45 if(inFile == NULL) {
46 fprintf(stderr, "Could not open input file %s\n", inFileName.c_str());
47 exit(1);
50 outFile = fopen(outFileName.c_str(), "wb");
51 if(outFile == NULL) {
52 fprintf(stderr, "Could not open output file %s\n", outFileName.c_str());
53 exit(1);
56 decode(inFile, outFile);
58 if(verbose) printf("\nClosing files\n");
59 fclose(inFile);
60 fclose(outFile);
61 return 0;
64 bool parseCommandLine(int argc, char **argv)
66 bool ret=false;
68 try {
70 //Video format options
71 po::options_description desc("Allowed Options");
72 desc.add_options()
73 ("help", " Show this message")
74 ("verbose,v", " Enable verbose decoding")
75 ("input", po::value(&inFileName), "string Dirac bitstream to decode")
76 ("output", po::value(&outFileName), "string YUV planar output file");
78 //the filenames are 'positional options'
79 po::positional_options_description p;
80 p.add("input", 1);
81 p.add("output", 2);
83 //do the command line parsing
84 po::variables_map vm;
85 po::store(po::command_line_parser(argc, argv). options(desc).positional(p).run(), vm);
86 po::notify(vm);
88 //decode flags
89 if(vm.count("verbose")) verbose=true;
90 if(vm.count("help")) {
91 std::cout << "Usage : schro_decode [flags] input output" << std::endl;
92 std::cout << desc << std::endl;
93 ret = true;
96 if(vm.count("input") == 0)
97 throw(std::runtime_error("No input file specified"));
99 if(vm.count("output") == 0)
100 throw(std::runtime_error("No output file specified"));
103 catch(std::exception& e)
105 printf("Command line error : ");
106 std::cout << e.what() << "\n";
107 ret = true;
110 return ret;
113 static void
114 buffer_free (SchroBuffer *buf, void *priv)
116 free (priv);
119 /* push the data through the decoder */
120 static void decode(FILE *infile, FILE *outfile)
122 SchroDecoder *decoder;
123 SchroBuffer *buffer;
124 SchroVideoFormat *format = NULL;
125 SchroFrame *frame;
126 bool go;
127 int it;
128 void *packet;
129 int size=-1;
130 int ret;
131 int framecount=0;
133 decoder = schro_decoder_new();
135 while(true) {
137 //on the previous iteration feof(inFile) = true, so stop
138 if(size == 0)
139 goto out;
141 //get a packet from the stream and push it to the decoder
142 ret = parse_packet (infile, &packet, &size);
143 if (!ret) {
144 //parse error
145 goto out;
148 if (size == 0) {
149 //unexpected end of file from parser
150 schro_decoder_push_end_of_stream (decoder);
151 } else {
152 buffer = schro_buffer_new_with_data (packet, size);
153 buffer->free = buffer_free;
154 buffer->priv = packet;
156 it = schro_decoder_push (decoder, buffer);
157 if (it == SCHRO_DECODER_FIRST_ACCESS_UNIT) {
158 format = schro_decoder_get_video_format (decoder);
159 if(verbose) {
160 printf("\nFirst Sequence Header:\n");
161 showVideoFormat(format);
166 //iterate the decoder until it needs more data
167 go = true;
168 while (go == true) {
169 it = schro_decoder_wait (decoder);
171 switch (it) {
172 case SCHRO_DECODER_NEED_BITS:
173 go = false;
174 break;
175 case SCHRO_DECODER_NEED_FRAME:
176 switch(format->chroma_format) {
177 case SCHRO_CHROMA_444:
178 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_444,
179 format->width, format->height);
180 break;
181 case SCHRO_CHROMA_422:
182 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_422,
183 format->width, format->height);
184 break;
185 case SCHRO_CHROMA_420:
186 frame = schro_frame_new_and_alloc (NULL, SCHRO_FRAME_FORMAT_U8_420,
187 format->width, format->height);
188 break;
189 default:
190 printf("error: unrecognised chroma format\n");
191 exit(1);
192 break;
194 schro_decoder_add_output_picture (decoder, frame);
195 break;
196 case SCHRO_DECODER_OK:
197 frame = schro_decoder_pull (decoder);
198 if (frame) {
199 if(verbose) {
200 printf("writing output frame %d\r", framecount++);
201 fflush(stdout);
203 // write frame data out in planar format
204 fwrite(frame->components[0].data, frame->components[0].length, 1, outfile);
205 fwrite(frame->components[1].data, frame->components[1].length, 1, outfile);
206 fwrite(frame->components[2].data, frame->components[2].length, 1, outfile);
207 schro_frame_unref(frame);
209 break;
210 case SCHRO_DECODER_EOS:
211 if(verbose) printf("\nGot End of Sequence");
212 schro_decoder_reset(decoder);
213 go = false;
214 break;
215 case SCHRO_DECODER_ERROR:
216 printf("\nerror: got decoder internal error - exiting\n");
217 goto out;
218 break;
223 out:
225 if(verbose) printf("\nFreeing decoder");
226 schro_decoder_free (decoder);
227 free(format);