Dirac parser.
[frameshot.git] / input / dirac.c
blob17c612a029b61299b508ad272e709be0e573fba6
1 #include <stdio.h>
2 #include <string.h>
3 #include <schroedinger/schro.h>
4 #include "common.h"
5 #include "dirac.h"
7 typedef struct {
8 FILE *fh;
9 SchroDecoder *p_schro;
10 SchroVideoFormat *p_format;
11 } dirac_input_t;
13 int parse_packet( dirac_input_t *h, uint8_t **pp_data, int *p_size );
14 static void buffer_free( SchroBuffer *buf, void *priv );
16 int open_file_dirac( char *psz_filename, hnd_t *p_handle, config_t *p_config )
18 int size = -1;
19 int it;
20 uint8_t *packet = NULL;
21 dirac_input_t *h = calloc(1, sizeof(*h));
22 SchroBuffer *buffer;
24 if( !strcmp(psz_filename, "-") )
25 h->fh = stdin;
26 else
27 h->fh = fopen(psz_filename, "rb");
28 if( h->fh == NULL )
29 return -1;
31 if( parse_packet( h, &packet, &size ) )
32 return -1;
34 if( size == 0 )
35 return -1;
37 schro_init();
39 h->p_schro = schro_decoder_new();
41 buffer = schro_buffer_new_with_data( packet, size );
42 buffer->free = buffer_free;
43 buffer->priv = packet;
45 it = schro_decoder_push( h->p_schro, buffer );
46 if( it == SCHRO_DECODER_FIRST_ACCESS_UNIT )
48 h->p_format = schro_decoder_get_video_format( h->p_schro );
51 if( h->p_format->interlaced )
52 fprintf( stderr, "warning: sequence may be interlaced!\n" );
54 p_config->i_width = h->p_format->width;
55 p_config->i_height = h->p_format->height;
56 switch(h->p_format->chroma_format) {
57 case SCHRO_CHROMA_420:
58 p_config->i_csp = COLORSPACE_420;
59 break;
60 case SCHRO_CHROMA_444:
61 case SCHRO_CHROMA_422:
62 fprintf( stderr, "ERROR: Unsupported chroma format.\n" );
63 return -1;
66 *p_handle = (hnd_t)h;
67 return 0;
70 int read_frame_dirac( hnd_t handle, picture_t *p_pic, int i_frame )
72 dirac_input_t *h = handle;
73 int size = -1;
74 uint8_t *packet;
75 SchroBuffer *buffer;
76 SchroFrame *frame;
77 int go = 1;
79 /* This function assumes that it will be called with i_frame increasing. */
80 schro_decoder_set_earliest_frame( h->p_schro, i_frame );
82 while( 1 ) {
84 /* Handle EOF from previous iteration */
85 if( size == 0 )
86 break;
88 go = 1;
89 while( go ) {
90 switch( schro_decoder_wait( h->p_schro ) ) {
91 case SCHRO_DECODER_NEED_BITS:
92 go = 0;
93 break;
94 case SCHRO_DECODER_NEED_FRAME:
95 switch(h->p_format->chroma_format) {
96 case SCHRO_CHROMA_444:
97 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_444,
98 h->p_format->width, h->p_format->height );
99 break;
100 case SCHRO_CHROMA_422:
101 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_422,
102 h->p_format->width, h->p_format->height );
103 break;
104 case SCHRO_CHROMA_420:
105 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_420,
106 h->p_format->width, h->p_format->height );
107 break;
108 default:
109 printf("ERROR: unsupported chroma format\n");
110 return -1;
112 schro_decoder_add_output_picture( h->p_schro, frame );
113 break;
114 case SCHRO_DECODER_OK:
116 int i_dts = schro_decoder_get_picture_number( h->p_schro );
117 frame = schro_decoder_pull( h->p_schro );
118 if( i_dts != i_frame )
120 /* This shouldn't happen, why does it? */
121 schro_frame_unref(frame);
122 break;
125 memcpy( p_pic->img.plane[0], frame->components[0].data, frame->components[0].length );
126 memcpy( p_pic->img.plane[1], frame->components[1].data, frame->components[1].length );
127 memcpy( p_pic->img.plane[2], frame->components[2].data, frame->components[2].length );
129 schro_frame_unref(frame);
130 return 0;
132 break;
133 case SCHRO_DECODER_EOS:
134 schro_decoder_reset( h->p_schro );
135 go = 0;
136 break;
137 case SCHRO_DECODER_ERROR:
138 break;
142 if( parse_packet( h, &packet, &size ) )
144 break;
147 if( size == 0 ) {
148 /* Unexpected EOF */
149 schro_decoder_push_end_of_stream( h->p_schro );
150 return -1;
151 } else {
152 buffer = schro_buffer_new_with_data( packet, size );
153 buffer->free = buffer_free;
154 buffer->priv = packet;
156 schro_decoder_push( h->p_schro, buffer );
161 return 0;
164 int close_file_dirac( hnd_t handle )
166 dirac_input_t *h = handle;
167 if( !h || !h->fh || !h->p_schro || !h->p_format )
168 return 0;
169 fclose( h->fh );
170 free( h->p_format );
171 schro_decoder_free( h->p_schro );
172 free( h );
173 return 0;
176 /* From schroedinger-tools */
177 int parse_packet( dirac_input_t *h, uint8_t **pp_data, int *p_size )
179 uint8_t *packet;
180 uint8_t header[13];
181 int n;
182 int size;
184 n = fread( header, 1, 13, h->fh );
185 if( feof( h->fh ) ) {
186 *pp_data = NULL;
187 *p_size = 0;
188 return 0;
190 if( n < 13 ) {
191 fprintf( stderr, "ERROR: truncated header\n" );
192 return -1;
195 if( header[0] != 'B' || header[1] != 'B' || header[2] != 'C' ||
196 header[3] != 'D' ) {
197 fprintf( stderr, "ERROR: header magic incorrect\n" );
198 return -1;
201 size = (header[5]<<24) | (header[6]<<16) | (header[7]<<8) | (header[8]);
202 if ( size == 0 ) {
203 size = 13;
205 if( size < 13 ) {
206 fprintf( stderr, "ERROR: packet too small? (%d)\n", size );
207 return -1;
209 if( size > 1<<24 ) {
210 fprintf( stderr, "ERROR: packet too large? (%d > 1<<24)\n", size );
211 return -1;
214 packet = malloc( size );
215 memcpy( packet, header, 13 );
216 n = fread( packet + 13, 1, size - 13, h->fh );
217 if( n < size - 13 ) {
218 free( packet );
219 return -1;
222 *pp_data = packet;
223 *p_size = size;
224 return 0;
227 static void buffer_free( SchroBuffer *buf, void *priv )
229 free (priv);