introduce enumerated return codes from parse_packet
[schroedinger-tools.git] / src / schro_encode.cpp
blobb943b7d846ac9ae9b84ba56cdba015fee23475b3
1 /* Schrodinger encoder wrapper for non GStreamer applications
2 * 2006 Jon Rosser BBC R&D
4 */
6 #include <iostream>
7 #include <stdio.h>
9 #include <schroedinger/schro.h>
11 #include "schrooptions.h"
12 #include <boost/program_options.hpp>
13 namespace po = boost::program_options;
15 #include "common.h"
17 /* global variables */
18 static std::string inFileName;
19 static std::string outFileName;
20 static FILE *inFile;
21 static FILE *outFile;
22 static int start_pos = 0;
23 static int end_pos = -1;
24 static SchroVideoFormat *format = NULL;
25 static SchroEncoder *encoder = NULL;
26 static bool verbose = false;
28 /* function prototypes */
29 static bool parseCommandLine(int argc, char *argv[]);
31 static void encode_frame_free (SchroFrame *frame, void *priv)
33 free (priv);
36 /* main coding loop */
37 int main(int argc, char *argv[])
39 SchroBuffer *buffer = NULL;
40 SchroFrame *frame = NULL;
41 int presentation_frame;
42 int inFrame = 0;
43 int go = 1;
45 schro_init();
46 encoder = schro_encoder_new();
47 format = schro_encoder_get_video_format(encoder);
49 if(parseCommandLine(argc, argv)) {
50 exit(1);
53 if(verbose) {
54 showVideoFormat(format);
55 showEncoderSettings(encoder);
58 if(schro_video_format_validate(format) != 1) {
59 printf("Video format is not valid for encoder\n");
60 exit(1);
63 schro_encoder_set_video_format(encoder, format);
64 size_t frame_size = (size_t)(format->width*format->height);
66 switch (format->chroma_format)
68 case SCHRO_CHROMA_444:
69 frame_size *= 3;
70 break;
71 case SCHRO_CHROMA_422:
72 frame_size *= 2;
73 break;
74 case SCHRO_CHROMA_420:
75 default:
76 frame_size = (frame_size*3)/2;
77 break;
80 /* open an input and output files */
81 inFile = fopen(inFileName.c_str(), "rb");
82 if (inFile == NULL)
84 printf("Could not open input file %s\n", inFileName.c_str());
85 exit(1);
88 outFile = fopen(outFileName.c_str(), "wb");
89 if (outFile == NULL)
91 printf("Could not open output file %s\n", outFileName.c_str());
92 exit(1);
95 /* seek into the file if required to satisfy start_pos */
96 if (start_pos != 0) fseek(inFile, (frame_size * start_pos), SEEK_CUR);
98 /* if end_pos is -1, make lots of frames */
99 if (end_pos == -1)
100 end_pos = INT_MAX;
102 /* encode the required number of frames */
103 schro_encoder_start (encoder);
104 do {
105 switch(schro_encoder_wait(encoder))
107 case SCHRO_STATE_NEED_FRAME:
110 unsigned char *buf = (unsigned char *)malloc(frame_size);
111 /* read from input file into frame */
112 if (inFrame > (end_pos - start_pos) ||fread (buf, 1, frame_size, inFile) != frame_size)
114 free(buf);
115 schro_encoder_end_of_stream(encoder);
117 else
119 /* make a new frame */
120 switch (format->chroma_format)
122 case SCHRO_CHROMA_444:
123 frame = frame_new_from_data_u8_planar444(buf, format->width, format->height);
124 break;
125 case SCHRO_CHROMA_422:
126 frame = frame_new_from_data_u8_planar422(buf, format->width, format->height);
127 break;
128 case SCHRO_CHROMA_420:
129 frame = schro_frame_new_from_data_I420(buf, format->width, format->height);
130 break;
131 default:
132 printf("error: unknown chroma format\n");
133 exit(1);
134 break;
136 schro_frame_set_free_callback (frame, encode_frame_free, buf);
137 if(verbose) {
138 printf("Pushing frame %d \r", inFrame++);
139 fflush(stdout);
141 schro_encoder_push_frame(encoder, frame);
143 break;
145 case SCHRO_STATE_HAVE_BUFFER:
146 buffer = schro_encoder_pull (encoder, &presentation_frame);
147 fwrite(buffer->data, 1, buffer->length, outFile);
148 schro_buffer_unref (buffer);
149 break;
151 case SCHRO_STATE_AGAIN:
152 break;
154 case SCHRO_STATE_END_OF_STREAM:
155 // pull end of stream info
156 buffer = schro_encoder_pull (encoder, &presentation_frame);
157 fwrite(buffer->data, 1, buffer->length, outFile);
158 schro_buffer_unref (buffer);
159 go = 0;
160 break;
162 default:
163 break;
166 //while ((inFrame <= (end_pos - start_pos)) && (feof(inFile) == 0) && go == 1);
167 while (go == 1);
169 printf("\nFinished encoding\n");
170 schro_encoder_free(encoder);
172 fclose(inFile);
173 fclose(outFile);
174 return 0;
177 bool parseCommandLine(int argc, char **argv)
179 int wrap_length=800; //make the internal line from boost have a really long line. The terminal does wrapping instead
180 po::variables_map vm;
182 try {
184 //Video format options
185 po::options_description video_coding_options("Video Format Options Used During Coding", wrap_length);
186 addVideoCodingOptions(video_coding_options);
188 po::options_description video_metadata_options("Video Format MetaData", wrap_length);
189 addVideoMetadataOptions(video_metadata_options);
191 po::options_description other_options("Other", wrap_length);
192 other_options.add_options()
193 ("start", po::value(&start_pos), "uint 0 \t Frame number to start coding")
194 ("stop", po::value(&end_pos), "uint EOF \t Frame number to stop coding")
195 ("verbose,v", "Show encoder settings before encoding")
196 ("input", po::value(&inFileName), "Planar YUV file to encode")
197 ("output", po::value(&outFileName), "Dirac bitstream output file")
198 ("help", "Show help");
200 //add dynamic options
201 po::options_description dynamic_options("Encoder Coding Options", wrap_length);
202 addDynamicOptions(dynamic_options);
204 //merge the groups of option descriptions
205 po::options_description all("Allowed Options");
206 all.add(video_coding_options).add(video_metadata_options).add(dynamic_options).add(other_options);
208 //the filenames are 'positional options'
209 po::positional_options_description p;
210 p.add("input", 1);
211 p.add("output", 2);
213 //do the command line parsing
214 po::store(po::command_line_parser(argc, argv). options(all).positional(p).run(), vm);
215 po::notify(vm);
217 //decode some overall flags
218 if(vm.count("verbose")) verbose=true;
219 if(vm.count("help")) {
220 std::cout << "Usage : schro_encode [flags] input output" << std::endl;
221 std::cout << video_coding_options << std::endl;
222 std::cout << video_metadata_options << std::endl;
223 std::cout << dynamic_options << std::endl;
224 std::cout << other_options << std::endl;
225 return true;
228 catch(std::exception& e)
230 printf("Command line error : ");
231 std::cout << e.what() << "\n";
232 return true;
235 applyVideoCodingOptions(format, vm);
236 applyVideoMetadataOptions(format, vm);
237 return applyDynamicOptions(encoder, vm);