Use strncmp() to check dirac parse header magic.
[frameshot.git] / input / dirac.c
blob98dc5712c04a1f3d70369a8f779fb247b3385929
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 #define DIRAC_PARSE_MAGIC "BBCD"
15 int parse_packet( dirac_input_t *h, uint8_t **pp_data, int *p_size );
16 static void buffer_free( SchroBuffer *buf, void *priv );
18 int open_file_dirac( char *psz_filename, hnd_t *p_handle, config_t *p_config )
20 int size = -1;
21 int it;
22 uint8_t *packet = NULL;
23 dirac_input_t *h = calloc(1, sizeof(*h));
24 SchroBuffer *buffer;
26 if( !strcmp(psz_filename, "-") )
27 h->fh = stdin;
28 else
29 h->fh = fopen(psz_filename, "rb");
30 if( h->fh == NULL )
31 return -1;
33 if( parse_packet( h, &packet, &size ) )
34 return -1;
36 if( size == 0 )
37 return -1;
39 schro_init();
41 h->p_schro = schro_decoder_new();
43 buffer = schro_buffer_new_with_data( packet, size );
44 buffer->free = buffer_free;
45 buffer->priv = packet;
47 it = schro_decoder_push( h->p_schro, buffer );
48 if( it == SCHRO_DECODER_FIRST_ACCESS_UNIT )
50 h->p_format = schro_decoder_get_video_format( h->p_schro );
53 if( h->p_format->interlaced )
54 fprintf( stderr, "warning: sequence may be interlaced!\n" );
56 p_config->i_width = h->p_format->width;
57 p_config->i_height = h->p_format->height;
58 switch(h->p_format->chroma_format) {
59 case SCHRO_CHROMA_420:
60 p_config->i_csp = COLORSPACE_420;
61 break;
62 case SCHRO_CHROMA_444:
63 case SCHRO_CHROMA_422:
64 fprintf( stderr, "ERROR: Unsupported chroma format.\n" );
65 return -1;
68 *p_handle = (hnd_t)h;
69 return 0;
72 int read_frame_dirac( hnd_t handle, picture_t *p_pic, int i_frame )
74 dirac_input_t *h = handle;
75 int size = -1;
76 uint8_t *packet;
77 SchroBuffer *buffer;
78 SchroFrame *frame;
79 int go = 1;
81 /* This function assumes that it will be called with i_frame increasing. */
82 schro_decoder_set_earliest_frame( h->p_schro, i_frame );
84 while( 1 ) {
86 /* Handle EOF from previous iteration */
87 if( size == 0 )
88 break;
90 go = 1;
91 while( go ) {
92 switch( schro_decoder_wait( h->p_schro ) ) {
93 case SCHRO_DECODER_NEED_BITS:
94 go = 0;
95 break;
96 case SCHRO_DECODER_NEED_FRAME:
97 switch(h->p_format->chroma_format) {
98 case SCHRO_CHROMA_444:
99 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_444,
100 h->p_format->width, h->p_format->height );
101 break;
102 case SCHRO_CHROMA_422:
103 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_422,
104 h->p_format->width, h->p_format->height );
105 break;
106 case SCHRO_CHROMA_420:
107 frame = schro_frame_new_and_alloc( NULL, SCHRO_FRAME_FORMAT_U8_420,
108 h->p_format->width, h->p_format->height );
109 break;
110 default:
111 printf("ERROR: unsupported chroma format\n");
112 return -1;
114 schro_decoder_add_output_picture( h->p_schro, frame );
115 break;
116 case SCHRO_DECODER_OK:
118 int i_dts = schro_decoder_get_picture_number( h->p_schro );
119 frame = schro_decoder_pull( h->p_schro );
120 if( i_dts != i_frame )
122 /* This shouldn't happen, why does it? */
123 schro_frame_unref(frame);
124 break;
127 memcpy( p_pic->img.plane[0], frame->components[0].data, frame->components[0].length );
128 memcpy( p_pic->img.plane[1], frame->components[1].data, frame->components[1].length );
129 memcpy( p_pic->img.plane[2], frame->components[2].data, frame->components[2].length );
131 schro_frame_unref(frame);
132 return 0;
134 break;
135 case SCHRO_DECODER_EOS:
136 schro_decoder_reset( h->p_schro );
137 go = 0;
138 break;
139 case SCHRO_DECODER_ERROR:
140 break;
144 if( parse_packet( h, &packet, &size ) )
146 break;
149 if( size == 0 ) {
150 /* Unexpected EOF */
151 schro_decoder_push_end_of_stream( h->p_schro );
152 return -1;
153 } else {
154 buffer = schro_buffer_new_with_data( packet, size );
155 buffer->free = buffer_free;
156 buffer->priv = packet;
158 schro_decoder_push( h->p_schro, buffer );
163 return 0;
166 int close_file_dirac( hnd_t handle )
168 dirac_input_t *h = handle;
169 if( !h || !h->fh || !h->p_schro || !h->p_format )
170 return 0;
171 fclose( h->fh );
172 free( h->p_format );
173 schro_decoder_free( h->p_schro );
174 free( h );
175 return 0;
178 /* From schroedinger-tools */
179 int parse_packet( dirac_input_t *h, uint8_t **pp_data, int *p_size )
181 uint8_t *packet;
182 uint8_t header[13];
183 int n;
184 int size;
186 n = fread( header, 1, 13, h->fh );
187 if( feof( h->fh ) ) {
188 *pp_data = NULL;
189 *p_size = 0;
190 return 0;
192 if( n < 13 ) {
193 fprintf( stderr, "ERROR: truncated header\n" );
194 return -1;
197 if( strncmp((char *)header, DIRAC_PARSE_MAGIC, strlen(DIRAC_PARSE_MAGIC)) ) {
198 fprintf( stderr, "ERROR: header magic incorrect\n" );
199 return -1;
202 size = (header[5]<<24) | (header[6]<<16) | (header[7]<<8) | (header[8]);
203 if ( size == 0 ) {
204 size = 13;
206 if( size < 13 ) {
207 fprintf( stderr, "ERROR: packet too small? (%d)\n", size );
208 return -1;
210 if( size > 1<<24 ) {
211 fprintf( stderr, "ERROR: packet too large? (%d > 1<<24)\n", size );
212 return -1;
215 packet = malloc( size );
216 memcpy( packet, header, 13 );
217 n = fread( packet + 13, 1, size - 13, h->fh );
218 if( n < size - 13 ) {
219 free( packet );
220 return -1;
223 *pp_data = packet;
224 *p_size = size;
225 return 0;
228 static void buffer_free( SchroBuffer *buf, void *priv )
230 free (priv);