1 // LiVES - ogg/theora/dirac/vorbis decoder plugin
2 // (c) G. Finch 2008 - 2010 <salsaman@xs4all.nl,salsaman@gmail.com>
3 // released under the GNU GPL 3 or later
4 // see file COPYING or www.gnu.org for details
5
6 // start decoding at the page whose granulepos converts to the highest frame number prior to the one you're looking for
7
8 // TODO - split this into demuxer and decoders
9
10 // ignore this, just some notes ----------
11 // decoders should have the functions:
12 // - recognise :: demuxer passes in the first packet of a stream, and a decoder claims it
13 // decoder tells how many more bos packets it needs (detect_stream)
14 // - pre_init :: demuxer passes in bos packets until the decoder has parsed them all (setup tracks)
15 // - init :: decoder initialises its internal data (attach_stream)
16 // - set_data :: decoder completes cdata
17
18 // - clear :: decoder frees stuff (detach_stream)
19
20
21 // granulepos to pos :: demuxer passes in something like a granulepos or a byte offset, decoder returns kframe,frame or
22 // sample offset [is this possible since it requires knowledge of demuxer and decoder ?]
23 // (granulepos_to_time)
24
25
26 // granulepos_2_frame and frame_2 _granulepos are problematic for splitting like this
27
28 // - decode packet (and return if we got a frame out) (ogg_*_read)
29
30 // - return same frame
31
32 // finalise (clip_data_free)
33 ///----------------------------------------------------------
34
35 #define NEED_CLONEFUNC
36
37 #include "decplugin.h"
38
39 ///////////////////////////////////////////////////////
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <sched.h>
47
48 #include <ogg/ogg.h>
49
50 #ifdef HAVE_THEORA
51 #include <theora/theora.h>
52 #endif
53
54 #ifdef HAVE_DIRAC
55 #include <schroedinger/schro.h>
56 #endif
57
58 #include <pthread.h>
59
60 #include "ogg_decoder.h"
61
62 #define NEED_FOURCC_COMPAT
63
64 #ifdef NEED_LOCAL_WEED
65 #include "../../../libweed/weed-compat.h"
66 #else
67 #include <weed/weed-compat.h>
68 #endif
69
70 static boolean ogg_data_process(lives_clip_data_t *cdata, void *yuvbuffer, boolean cont);
71
72 static const char *plname = "lives_ogg";
73 static int vmaj = 1;
74 static int vmin = 2;
75 static const char *plugin_version = "LiVES ogg decoder version 1.2";
76
77 static index_container_t **indices;
78 static int nidxc;
79 static pthread_mutex_t indices_mutex;
80
81
82 /////////////////////////////////////////
83 // schroed stuff
84
85 #ifdef HAVE_DIRAC
SchroFrameFree(SchroFrame * sframe,void * priv)86 static void SchroFrameFree(SchroFrame *sframe, void *priv) {
87 register int i;
88 for (i = 0; i < 3; i++) free(sframe->components[i].data);
89 }
90
91
SchroBufferFree(SchroBuffer * sbuf,void * priv)92 static void SchroBufferFree(SchroBuffer *sbuf, void *priv) {
93 free(priv);
94 }
95
96
97 #endif
98
99 ////////////////////////////////////////////
100
101 // index_entries
102
103
index_entries_free(index_entry * idx)104 static void index_entries_free(index_entry *idx) {
105 index_entry *idx_next;
106
107 while (idx != NULL) {
108 idx_next = idx->next;
109 free(idx);
110 idx = idx_next;
111 }
112 }
113
114
index_entry_new(void)115 static index_entry *index_entry_new(void) {
116 index_entry *ie = (index_entry *)malloc(sizeof(index_entry));
117 ie->next = ie->prev = NULL;
118 ie->pagepos_end = -1;
119 return ie;
120 }
121
122
123 #ifdef HAVE_DIRAC
124
index_entry_delete(index_entry * idx)125 static index_entry *index_entry_delete(index_entry *idx) {
126 // unlink and free idx. If idx is head of list, return new head.
127
128 index_entry *xidx = idx;
129
130 if (idx->prev != NULL) idx->prev->next = idx->next;
131 else xidx = idx->next;
132
133 if (idx->next != NULL) idx->next->prev = idx->prev;
134 free(idx);
135
136 return xidx;
137 }
138
139
find_pagepos_in_index(index_entry * idx,int64_t pagepos)140 static index_entry *find_pagepos_in_index(index_entry *idx, int64_t pagepos) {
141 while (idx != NULL) {
142 if (idx->pagepos <= pagepos && idx->pagepos_end >= pagepos) return idx;
143 idx = idx->next;
144 }
145 return NULL;
146 }
147
148 #endif
149
150
theora_index_entry_add(lives_clip_data_t * cdata,int64_t granule,int64_t pagepos)151 static index_entry *theora_index_entry_add(lives_clip_data_t *cdata, int64_t granule, int64_t pagepos) {
152 // add or update entry for keyframe and return it
153 index_entry *idx, *oidx, *last_idx = NULL;
154 int64_t gpos, frame, kframe, tframe, tkframe;
155
156 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
157
158 if (priv->vstream == NULL) return NULL;
159
160 tkframe = granule >> priv->vstream->stpriv->keyframe_granule_shift;
161 tframe = tkframe + granule - (tkframe << priv->vstream->stpriv->keyframe_granule_shift);
162
163 if (tkframe < 1) return NULL;
164
165 oidx = idx = priv->idxc->idx;
166
167 if (!idx) {
168 index_entry *ie = index_entry_new();
169 ie->value = granule;
170 ie->pagepos = pagepos;
171 priv->idxc->idx = ie;
172 return ie;
173 }
174
175 while (idx) {
176 gpos = idx->value;
177
178 kframe = gpos >> priv->vstream->stpriv->keyframe_granule_shift;
179 if (kframe > tframe) break;
180
181 if (kframe == tkframe) {
182 // entry exists, update it if applicable, and return it in found
183 frame = kframe + gpos - (kframe << priv->vstream->stpriv->keyframe_granule_shift);
184 if (frame < tframe) {
185 idx->value = granule;
186 idx->pagepos = pagepos;
187 }
188 return idx;
189 }
190
191 last_idx = idx;
192 idx = idx->next;
193 }
194
195 // insert after last_idx
196
197 idx = index_entry_new();
198
199 if (last_idx) {
200 idx->next = last_idx->next;
201 last_idx->next = idx;
202 idx->prev = last_idx;
203 } else {
204 idx->next = oidx;
205 oidx = idx;
206 }
207
208 if (idx->next) {
209 idx->next->prev = idx;
210 }
211
212 idx->value = granule;
213 idx->pagepos = pagepos;
214
215 return idx;
216 }
217
218 #ifdef HAVE_DIRAC
219
dirac_index_entry_add_before(index_entry * idx,int64_t pagepos)220 static index_entry *dirac_index_entry_add_before(index_entry *idx, int64_t pagepos) {
221 index_entry *new_idx = index_entry_new();
222
223 new_idx->value = -1;
224 new_idx->pagepos = pagepos;
225
226 if (idx) {
227 new_idx->next = idx;
228 new_idx->prev = idx->prev;
229 if (idx->prev) idx->prev->next = new_idx;
230 idx->prev = new_idx;
231 }
232 return new_idx;
233 }
234
235
dirac_index_entry_add(lives_clip_data_t * cdata,int64_t pagepos,int64_t pagepos_end,int64_t frame)236 static index_entry *dirac_index_entry_add(lives_clip_data_t *cdata, int64_t pagepos, int64_t pagepos_end,
237 int64_t frame) {
238 // add a new entry in order, and return a pointer to it
239
240 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
241 index_entry *new_idx = priv->idxc->idx, *last_idx = NULL;
242
243 //printf("ADDING IDX for frame %ld region %ld to %ld\n",frame,pagepos,pagepos_end);
244
245 //if (pagepos_end<pagepos) return NULL; // TODO ***
246
247 while (new_idx) {
248 if (new_idx->pagepos > pagepos) {
249 new_idx = dirac_index_entry_add_before(new_idx, pagepos);
250 new_idx->value = frame;
251 new_idx->pagepos_end = pagepos_end;
252
253 return new_idx;
254 }
255 last_idx = new_idx;
256 new_idx = new_idx->next;
257 }
258
259 // add as last enry
260
261 new_idx = index_entry_new();
262 new_idx->value = frame;
263 new_idx->pagepos = pagepos;
264 new_idx->pagepos_end = pagepos_end;
265
266 if (last_idx) {
267 new_idx->prev = last_idx;
268 last_idx->next = new_idx;
269 }
270
271 return new_idx;
272 }
273
274 #endif
275
get_bounds_for(lives_clip_data_t * cdata,int64_t tframe,int64_t * ppos_lower,int64_t * ppos_upper)276 static index_entry *get_bounds_for(lives_clip_data_t *cdata, int64_t tframe, int64_t *ppos_lower, int64_t *ppos_upper) {
277 // find upper and lower pagepos for frame; if we find an exact match, we return it
278 int64_t kframe, frame, gpos;
279
280 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
281 index_entry *idx = priv->idxc->idx;
282
283 *ppos_lower = *ppos_upper = -1;
284
285 while (idx) {
286 if (idx->pagepos < 0) {
287 // kframe was found to be invalid
288 idx = idx->next;
289 continue;
290 }
291
292 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
293 gpos = idx->value;
294 kframe = gpos >> priv->vstream->stpriv->keyframe_granule_shift;
295 frame = kframe + gpos - (kframe << priv->vstream->stpriv->keyframe_granule_shift);
296 } else {
297 kframe = frame = idx->value;
298 }
299
300 //fprintf(stderr,"check %lld against %lld\n",tframe,kframe);
301
302 if (kframe > tframe) {
303 *ppos_upper = idx->pagepos;
304 return NULL;
305 }
306
307 //fprintf(stderr,"2check against %lld\n",frame);
308 if (frame < tframe) {
309 *ppos_lower = idx->pagepos;
310 idx = idx->next;
311 continue;
312 }
313 //fprintf(stderr,"gotit 1\n");
314 return idx;
315 }
316 //fprintf(stderr,"not 1\n");
317 return NULL;
318 }
319
320
321 /////////////////////////////////////////////////////
322
323 #ifdef HAVE_THEORA
ptr_2_op(uint8_t * ptr,ogg_packet * op)324 static uint8_t *ptr_2_op(uint8_t *ptr, ogg_packet *op) {
325 memcpy(op, ptr, sizeof(*op));
326 ptr += sizeof(*op);
327 op->packet = ptr;
328 ptr += op->bytes;
329 return ptr;
330 }
331 #endif
332
333
get_page(lives_clip_data_t * cdata,int64_t inpos)334 static int64_t get_page(lives_clip_data_t *cdata, int64_t inpos) {
335 uint8_t header[PAGE_HEADER_BYTES + 255];
336 int nsegs, i;
337 int64_t result, gpos;
338 int page_size;
339 char *buf;
340
341 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
342 ogg_t *opriv = priv->opriv;
343
344 if (opriv->page_valid) {
345 fprintf(stderr, "page valid !\n");
346 return 0;
347 }
348
349 lseek64(opriv->fd, inpos, SEEK_SET);
350
351 if (read(opriv->fd, header, PAGE_HEADER_BYTES) < PAGE_HEADER_BYTES) {
352 lseek64(opriv->fd, inpos, SEEK_SET);
353 return 0;
354 }
355
356 nsegs = header[PAGE_HEADER_BYTES - 1];
357
358 if (read(opriv->fd, header + PAGE_HEADER_BYTES, nsegs) < nsegs) {
359 lseek64(opriv->fd, inpos, SEEK_SET);
360 return 0;
361 }
362
363 page_size = PAGE_HEADER_BYTES + nsegs;
364
365 for (i = 0; i < nsegs; i++) page_size += header[PAGE_HEADER_BYTES + i];
366
367 ogg_sync_reset(&opriv->oy);
368
369 buf = ogg_sync_buffer(&(opriv->oy), page_size);
370
371 memcpy(buf, header, PAGE_HEADER_BYTES + nsegs);
372
373 result = read(opriv->fd, (uint8_t *)buf + PAGE_HEADER_BYTES + nsegs, page_size - PAGE_HEADER_BYTES - nsegs);
374
375 ogg_sync_wrote(&(opriv->oy), result + PAGE_HEADER_BYTES + nsegs);
376
377 if (ogg_sync_pageout(&(opriv->oy), &(opriv->current_page)) != 1) {
378 //fprintf(stderr, "Got no packet %lld %d %s\n",result,page_size,buf);
379 return 0;
380 }
381
382 //fprintf(stderr, "Got packet %lld %d %s\n",result,page_size,buf);
383
384 if (priv->vstream) {
385 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
386 if (ogg_page_serialno(&(opriv->current_page)) == priv->vstream->stream_id) {
387 gpos = ogg_page_granulepos(&(opriv->current_page));
388 pthread_mutex_lock(&priv->idxc->mutex);
389 theora_index_entry_add(cdata, gpos, inpos);
390 pthread_mutex_unlock(&priv->idxc->mutex);
391 }
392 }
393 }
394
395 opriv->page_valid = 1;
396 return result + PAGE_HEADER_BYTES + nsegs;
397 }
398
399
detect_stream(ogg_packet * op)400 static uint32_t detect_stream(ogg_packet *op) {
401 // TODO - do this in the decoder plugins (not in demuxer)
402
403 //fprintf(stderr,"detecting stream\n");
404 if ((op->bytes > 7) &&
405 (op->packet[0] == 0x01) &&
406 !strncmp((char *)(op->packet + 1), "vorbis", 6)) {
407 //fprintf(stderr,"vorbis found\n");
408 return FOURCC_VORBIS;
409 } else if ((op->bytes > 7) &&
410 (op->packet[0] == 0x80) &&
411 !strncmp((char *)(op->packet + 1), "theora", 6)) {
412 //fprintf(stderr,"theora found\n");
413 return FOURCC_THEORA;
414 } else if ((op->bytes > 5) &&
415 (op->packet[4] == 0x00) &&
416 !strncmp((char *)(op->packet), "BBCD", 4)) {
417 //fprintf(stderr,"dirac found\n");
418 return FOURCC_DIRAC;
419 } else if ((op->bytes > 8) &&
420 (op->packet[8] == 0x00) &&
421 !strncmp((char *)(op->packet), "KW-DIRAC", 8)) {
422 //fprintf(stderr,"dirac found\n");
423 return FOURCC_DIRAC;
424 }
425
426 return 0;
427 }
428
429 #define PTR_2_32BE(p) \
430 ((*(p) << 24) | \
431 (*(p+1) << 16) | \
432 (*(p+2) << 8) | \
433 *(p+3))
434
435 #define PTR_2_32LE(p) \
436 ((*(p+3) << 24) | \
437 (*(p+2) << 16) | \
438 (*(p+1) << 8) | \
439 *(p))
440
441
lives_in_stream_new(int type)442 static lives_in_stream *lives_in_stream_new(int type) {
443 lives_in_stream *lstream = (lives_in_stream *)malloc(sizeof(lives_in_stream));
444 lstream->type = type;
445 lstream->ext_data = NULL;
446 lstream->ext_size = 0;
447 return lstream;
448 }
449
450
append_extradata(lives_in_stream * s,ogg_packet * op)451 static void append_extradata(lives_in_stream *s, ogg_packet *op) {
452 s->ext_data = realloc(s->ext_data, s->ext_size + sizeof(*op) + op->bytes);
453 memcpy(s->ext_data + s->ext_size, op, sizeof(*op));
454 memcpy(s->ext_data + s->ext_size + sizeof(*op), op->packet, op->bytes);
455 s->ext_size += (sizeof(*op) + op->bytes);
456 }
457
458
stream_from_sno(lives_clip_data_t * cdata,int sno)459 static inline lives_in_stream *stream_from_sno(lives_clip_data_t *cdata, int sno) {
460 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
461 if (priv->astream && sno == priv->astream->stream_id) return priv->astream;
462 if (priv->vstream && sno == priv->vstream->stream_id) return priv->vstream;
463 return NULL;
464 }
465
466
dirac_uint(bs_t * p_bs)467 static uint32_t dirac_uint(bs_t *p_bs) {
468 uint32_t u_count = 0, u_value = 0;
469
470 while (!bs_eof(p_bs) && !bs_read(p_bs, 1)) {
471 u_count++;
472 u_value <<= 1;
473 u_value |= bs_read(p_bs, 1);
474 }
475
476 return (1 << u_count) - 1 + u_value;
477 }
478
479
dirac_bool(bs_t * p_bs)480 static int dirac_bool(bs_t *p_bs) {
481 return bs_read(p_bs, 1);
482 }
483
484
idxc_for(lives_clip_data_t * cdata)485 static index_container_t *idxc_for(lives_clip_data_t *cdata) {
486 // check all idxc for string match with URI
487 index_container_t *idxc;
488 register int i;
489
490 pthread_mutex_lock(&indices_mutex);
491
492 for (i = 0; i < nidxc; i++) {
493 if (indices[i]->clients[0]->current_clip == cdata->current_clip &&
494 !strcmp(indices[i]->clients[0]->URI, cdata->URI)) {
495 idxc = indices[i];
496 // append cdata to clients
497 idxc->clients = (lives_clip_data_t **)realloc(idxc->clients, (idxc->nclients + 1) * sizeof(lives_clip_data_t *));
498 idxc->clients[idxc->nclients] = cdata;
499 idxc->nclients++;
500 //
501 pthread_mutex_unlock(&indices_mutex);
502 return idxc;
503 }
504 }
505
506 indices = (index_container_t **)realloc(indices, (nidxc + 1) * sizeof(index_container_t *));
507
508 // match not found, create a new index container
509 idxc = (index_container_t *)malloc(sizeof(index_container_t));
510
511 idxc->idx = NULL;
512
513 idxc->nclients = 1;
514 idxc->clients = (lives_clip_data_t **)malloc(sizeof(lives_clip_data_t *));
515 idxc->clients[0] = cdata;
516 pthread_mutex_init(&idxc->mutex, NULL);
517
518 indices[nidxc] = idxc;
519 pthread_mutex_unlock(&indices_mutex);
520
521 nidxc++;
522
523 return idxc;
524 }
525
526
idxc_release(lives_clip_data_t * cdata)527 static void idxc_release(lives_clip_data_t *cdata) {
528 lives_ogg_priv_t *priv = cdata->priv;
529 index_container_t *idxc = priv->idxc;
530 register int i, j;
531
532 if (idxc == NULL) return;
533
534 pthread_mutex_lock(&indices_mutex);
535
536 if (idxc->nclients == 1) {
537 // remove this index
538 index_entries_free(idxc->idx);
539 free(idxc->clients);
540 for (i = 0; i < nidxc; i++) {
541 if (indices[i] == idxc) {
542 nidxc--;
543 for (j = i; j < nidxc; j++) {
544 indices[j] = indices[j + 1];
545 }
546 free(idxc);
547 if (nidxc == 0) {
548 free(indices);
549 indices = NULL;
550 } else indices = (index_container_t **)realloc(indices, nidxc * sizeof(index_container_t *));
551 break;
552 }
553 }
554 } else {
555 // reduce client count by 1
556 for (i = 0; i < idxc->nclients; i++) {
557 if (idxc->clients[i] == cdata) {
558 // remove this entry
559 idxc->nclients--;
560 for (j = i; j < idxc->nclients; j++) {
561 idxc->clients[j] = idxc->clients[j + 1];
562 }
563 idxc->clients = (lives_clip_data_t **)realloc(idxc->clients, idxc->nclients * sizeof(lives_clip_data_t *));
564 break;
565 }
566 }
567 }
568
569 pthread_mutex_unlock(&indices_mutex);
570 }
571
572
idxc_release_all(void)573 static void idxc_release_all(void) {
574 register int i;
575
576 for (i = 0; i < nidxc; i++) {
577 index_entries_free(indices[i]->idx);
578 free(indices[i]->clients);
579 free(indices[i]);
580 }
581 nidxc = 0;
582 }
583
584
setup_tracks(lives_clip_data_t * cdata)585 static int setup_tracks(lives_clip_data_t *cdata) {
586 // pull first audio and video streams
587
588 // some constants for dirac (from vlc)
589 static const struct {
590 uint32_t u_n /* numerator */, u_d /* denominator */;
591 } p_dirac_frate_tbl[] = { /* table 10.3 */
592 {1, 1}, /* this first value is never used */
593 {24000, 1001}, {24, 1}, {25, 1}, {30000, 1001}, {30, 1},
594 {50, 1}, {60000, 1001}, {60, 1}, {15000, 1001}, {25, 2},
595 };
596 static const size_t u_dirac_frate_tbl = sizeof(p_dirac_frate_tbl) / sizeof(*p_dirac_frate_tbl);
597
598 static const uint32_t pu_dirac_vidfmt_frate[] = { /* table C.1 */
599 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
600 };
601 static const size_t u_dirac_vidfmt_frate = sizeof(pu_dirac_vidfmt_frate) / sizeof(*pu_dirac_vidfmt_frate);
602
603 ////////////////////////////////
604
605 int done;
606 stream_priv_t *ogg_stream;
607 int serialno;
608 int header_bytes = 0;
609 int64_t input_pos;
610
611 uint8_t imajor, iminor;
612
613 #ifdef HAVE_THEORA
614 uint8_t isubminor;
615 #endif
616
617 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
618 ogg_t *opriv = priv->opriv;
619
620 uint32_t u_video_format, u_n, u_d;
621
622 bs_t bs;
623
624 opriv->page_valid = 0;
625
626 lseek64(opriv->fd, 0, SEEK_SET);
627 priv->input_position = 0;
628
629 /* Get the first page of each stream */
630 while (1) {
631 if (!(input_pos = get_page(cdata, priv->input_position))) {
632 //fprintf(stderr, "EOF1 while setting up track\n");
633 return 0;
634 }
635
636 priv->input_position += input_pos;
637
638 if (!ogg_page_bos(&(opriv->current_page))) {
639 opriv->page_valid = 1;
640 break;
641 }
642
643 /* Setup stream */
644 serialno = ogg_page_serialno(&(opriv->current_page));
645 ogg_stream = calloc(1, sizeof(*ogg_stream));
646 ogg_stream->last_granulepos = -1;
647
648 ogg_stream_init(&ogg_stream->os, serialno);
649 ogg_stream_pagein(&ogg_stream->os, &(opriv->current_page));
650 opriv->page_valid = 0;
651 header_bytes += opriv->current_page.header_len + opriv->current_page.body_len;
652
653 if (ogg_stream_packetout(&ogg_stream->os, &opriv->op) != 1) {
654 fprintf(stderr, "EOF3 while setting up track\n");
655 ogg_stream_clear(&ogg_stream->os);
656 free(ogg_stream);
657 return 0;
658 }
659
660 // TODO - do stream detection in decoder plugins
661
662 ogg_stream->fourcc_priv = detect_stream(&opriv->op);
663
664 switch (ogg_stream->fourcc_priv) {
665 case FOURCC_VORBIS:
666 if (priv->astream != NULL) {
667 fprintf(stderr, "got extra audio stream\n");
668 ogg_stream_clear(&ogg_stream->os);
669 free(ogg_stream);
670 break;
671 }
672 priv->astream = lives_in_stream_new(LIVES_STREAM_AUDIO);
673 priv->astream->fourcc = FOURCC_VORBIS;
674 priv->astream->stpriv = ogg_stream;
675 priv->astream->stream_id = serialno;
676
677 ogg_stream->header_packets_needed = 3;
678 append_extradata(priv->astream, &opriv->op);
679 ogg_stream->header_packets_read = 1;
680
681 /* Get samplerate */
682 priv->astream->samplerate = PTR_2_32LE(opriv->op.packet + 12);
683 //fprintf(stderr,"rate is %d\n",priv->astream->samplerate);
684
685 /* Read remaining header packets from this page */
686 while (ogg_stream_packetout(&ogg_stream->os, &opriv->op) == 1) {
687 append_extradata(priv->astream, &opriv->op);
688 ogg_stream->header_packets_read++;
689 if (ogg_stream->header_packets_read == ogg_stream->header_packets_needed) break;
690 }
691 break;
692 #ifdef HAVE_THEORA
693 case FOURCC_THEORA:
694 if (priv->vstream != NULL) {
695 fprintf(stderr, "got extra video stream\n");
696 ogg_stream_clear(&ogg_stream->os);
697 free(ogg_stream);
698 break;
699 }
700 priv->vstream = lives_in_stream_new(LIVES_STREAM_VIDEO);
701 priv->vstream->fourcc = FOURCC_THEORA;
702 priv->vstream->stpriv = ogg_stream;
703 priv->vstream->stream_id = serialno;
704
705 ogg_stream->header_packets_needed = 3;
706 append_extradata(priv->vstream, &opriv->op);
707 ogg_stream->header_packets_read = 1;
708
709 priv->vstream->data_start = 0;
710
711 /* get version */
712 imajor = ((uint8_t *)(priv->vstream->ext_data))[55];
713 iminor = ((uint8_t *)(priv->vstream->ext_data))[56];
714 isubminor = ((uint8_t *)(priv->vstream->ext_data))[57];
715
716 priv->vstream->version = imajor * 1000000 + iminor * 1000 + isubminor;
717
718 // TODO - get frame width, height, picture width, height, and x and y offsets
719
720 cdata->seek_flag = LIVES_SEEK_FAST | LIVES_SEEK_NEEDS_CALCULATION;
721
722 /* Get fps and keyframe shift */
723 priv->vstream->fps_num = PTR_2_32BE(opriv->op.packet + 22);
724 priv->vstream->fps_denom = PTR_2_32BE(opriv->op.packet + 26);
725
726 //fprintf(stderr,"fps is %d / %d\n",priv->vstream->fps_num,priv->vstream->fps_denom);
727
728 ogg_stream->keyframe_granule_shift = (char)((opriv->op.packet[40] & 0x03) << 3);
729 ogg_stream->keyframe_granule_shift |= (opriv->op.packet[41] & 0xe0) >> 5;
730
731 /* Read remaining header packets from this page */
732 while (ogg_stream_packetout(&ogg_stream->os, &opriv->op) == 1) {
733 append_extradata(priv->vstream, &opriv->op);
734 ogg_stream->header_packets_read++;
735 if (ogg_stream->header_packets_read == ogg_stream->header_packets_needed) break;
736 }
737
738 break;
739 #endif
740 case FOURCC_DIRAC:
741 if (priv->vstream != NULL) {
742 fprintf(stderr, "got extra video stream\n");
743 ogg_stream_clear(&ogg_stream->os);
744 free(ogg_stream);
745 break;
746 }
747
748 priv->vstream = lives_in_stream_new(LIVES_STREAM_VIDEO);
749 priv->vstream->fourcc = FOURCC_DIRAC;
750 priv->vstream->stpriv = ogg_stream;
751 priv->vstream->stream_id = serialno;
752
753 priv->vstream->data_start = priv->input_position - input_pos;
754
755 ogg_stream->header_packets_needed = 0;
756 ogg_stream->header_packets_read = 1;
757
758 ogg_stream->keyframe_granule_shift = 22; /* not 32 */
759
760 /* read in useful bits from sequence header */
761 bs_init(&bs, &opriv->op.packet, opriv->op.bytes);
762
763 /* get version */
764 bs_skip(&bs, 13 * 8); /* parse_info_header */
765
766 imajor = dirac_uint(&bs); /* major_version */
767 iminor = dirac_uint(&bs); /* minor_version */
768 //iprof=dirac_uint( &bs ); /* profile */
769 //ilevel=dirac_uint( &bs ); /* level */
770
771 priv->vstream->version = imajor * 1000000 + iminor * 1000;
772
773 //printf("dirac version %d\n",priv->vstream->version);
774
775 u_video_format = dirac_uint(&bs); /* index */
776 if (u_video_format >= u_dirac_vidfmt_frate) {
777 /* don't know how to parse this ogg dirac stream */
778 ogg_stream_clear(&ogg_stream->os);
779 free(ogg_stream);
780 free(priv->vstream);
781 priv->vstream = NULL;
782 break;
783 }
784
785 if (dirac_bool(&bs)) {
786 cdata->frame_width = cdata->width = dirac_uint(&bs); /* frame_width */
787 cdata->frame_height = cdata->width = dirac_uint(&bs); /* frame_height */
788 }
789 // else...????
790
791 if (dirac_bool(&bs)) {
792 dirac_uint(&bs); /* chroma_format */
793 }
794
795 if (dirac_bool(&bs)) {
796 dirac_uint(&bs); /* scan_format */
797 }
798
799 u_n = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_n;
800 u_d = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_d;
801
802 if (dirac_bool(&bs)) {
803 uint32_t u_frame_rate_index = dirac_uint(&bs);
804 if (u_frame_rate_index >= u_dirac_frate_tbl) {
805 /* something is wrong with this stream */
806 ogg_stream_clear(&ogg_stream->os);
807 free(ogg_stream);
808 free(priv->vstream);
809 priv->vstream = NULL;
810 break;
811 }
812 u_n = p_dirac_frate_tbl[u_frame_rate_index].u_n;
813 u_d = p_dirac_frate_tbl[u_frame_rate_index].u_d;
814 if (u_frame_rate_index == 0) {
815 u_n = dirac_uint(&bs); /* frame_rate_numerator */
816 u_d = dirac_uint(&bs); /* frame_rate_denominator */
817 }
818 }
819
820 cdata->fps = (float) u_n / (float) u_d;
821
822 cdata->seek_flag = LIVES_SEEK_FAST | LIVES_SEEK_NEEDS_CALCULATION | LIVES_SEEK_QUALITY_LOSS;
823
824 priv->vstream->fps_num = u_n;
825 priv->vstream->fps_denom = u_d;
826
827 break;
828
829 default:
830 ogg_stream_clear(&ogg_stream->os);
831 free(ogg_stream);
832 break;
833 }
834 }
835
836 if (priv->vstream == NULL) return 0;
837
838 /*
839 Now, read header pages until we are done, current_page still contains the
840 first page which has no bos marker set
841 */
842
843 done = 0;
844 while (!done) {
845 lives_in_stream *stream = stream_from_sno(cdata, ogg_page_serialno(&(opriv->current_page)));
846 if (stream) {
847 ogg_stream = (stream_priv_t *)(stream->stpriv);
848 ogg_stream_pagein(&(ogg_stream->os), &(opriv->current_page));
849 opriv->page_valid = 0;
850 header_bytes += opriv->current_page.header_len + opriv->current_page.body_len;
851
852 switch (ogg_stream->fourcc_priv) {
853 case FOURCC_THEORA:
854 case FOURCC_VORBIS:
855 /* Read remaining header packets from this page */
856 while (ogg_stream_packetout(&ogg_stream->os, &opriv->op) == 1) {
857 append_extradata(stream, &opriv->op);
858 ogg_stream->header_packets_read++;
859 /* Second packet is vorbis comment starting after 7 bytes */
860 //if (ogg_stream->header_packets_read == 2) parse_vorbis_comment(stream, opriv->op.packet + 7, opriv->op.bytes - 7);
861 if (ogg_stream->header_packets_read == ogg_stream->header_packets_needed) break;
862 }
863 break;
864 }
865 } else {
866 opriv->page_valid = 0;
867 header_bytes += opriv->current_page.header_len + opriv->current_page.body_len;
868 }
869
870 /* Check if we are done for all streams */
871 done = 1;
872
873 //for (i = 0; i < track->num_audio_streams; i++) {
874 if (priv->astream != NULL) {
875 ogg_stream = priv->astream->stpriv;
876 if (ogg_stream->header_packets_read < ogg_stream->header_packets_needed) done = 0;
877 }
878
879 if (done) {
880 //for(i = 0; i < track->num_video_streams; i++)
881 //{
882 if (priv->vstream != NULL) {
883 ogg_stream = priv->vstream->stpriv;
884 if (ogg_stream->header_packets_read < ogg_stream->header_packets_needed) done = 0;
885 }
886 }
887 //}
888
889 /* Read the next page if we aren't done yet */
890
891 if (!done) {
892 if (!(input_pos = get_page(cdata, priv->input_position))) {
893 fprintf(stderr, "EOF2 while setting up track");
894 return 0;
895 }
896 priv->input_position += input_pos;
897 }
898 }
899
900 if (priv->vstream->data_start == 0) priv->vstream->data_start = priv->input_position;
901
902 return 1;
903 }
904
905
906 #ifdef HAVE_DIRAC
get_dirac_cdata(lives_clip_data_t * cdata,SchroDecoder * schrodec)907 void get_dirac_cdata(lives_clip_data_t *cdata, SchroDecoder *schrodec) {
908 SchroVideoFormat *sformat = schro_decoder_get_video_format(schrodec);
909 cdata->frame_width = sformat->width;
910 cdata->frame_height = sformat->height;
911
912 cdata->width = sformat->clean_width;
913 cdata->height = (sformat->clean_height >> 1) << 1;
914
915 if (sformat->interlaced) {
916 if (sformat->top_field_first) cdata->interlace = LIVES_INTERLACE_TOP_FIRST;
917 else cdata->interlace = LIVES_INTERLACE_BOTTOM_FIRST;
918 } else cdata->interlace = LIVES_INTERLACE_NONE;
919
920 switch (sformat->chroma_format) {
921 case SCHRO_CHROMA_420:
922 cdata->palettes[0] = WEED_PALETTE_YUV420P;
923 break;
924 case SCHRO_CHROMA_422:
925 cdata->palettes[0] = WEED_PALETTE_YUV422P;
926 break;
927 case SCHRO_CHROMA_444:
928 cdata->palettes[0] = WEED_PALETTE_YUV444P;
929 break;
930 default:
931 cdata->palettes[0] = WEED_PALETTE_END;
932 break;
933 }
934
935 //if (sformat->colour_matrix==SCHRO_COLOUR_MATRIX_HDTV) cdata->YUV_subspace=WEED_YUV_SUBSPACE_BT709;
936
937 cdata->offs_x = sformat->left_offset;
938 cdata->offs_y = sformat->top_offset;
939
940 cdata->par = sformat->aspect_ratio_numerator / sformat->aspect_ratio_denominator;
941
942 if (sformat->luma_offset == 0) cdata->YUV_clamping = WEED_YUV_CLAMPING_UNCLAMPED;
943 else cdata->YUV_clamping = WEED_YUV_CLAMPING_CLAMPED;
944
945 //printf("vals %d %d %d %d %d %d\n",sformat->width,sformat->height,sformat->clean_width,sformat->clean_height,sformat->interlaced,cdata->palettes[0]);
946
947 free(sformat);
948 }
949 #endif
950
951
seek_byte(lives_clip_data_t * cdata,int64_t pos)952 static void seek_byte(lives_clip_data_t *cdata, int64_t pos) {
953 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
954 ogg_t *opriv = priv->opriv;
955
956 ogg_sync_reset(&(opriv->oy));
957 lseek64(opriv->fd, pos, SEEK_SET);
958 priv->input_position = pos;
959 opriv->page_valid = 0;
960 }
961
962
963 /* Get new data */
964
get_data(lives_clip_data_t * cdata,size_t bytes_to_read)965 static int64_t get_data(lives_clip_data_t *cdata, size_t bytes_to_read) {
966 char *buf;
967 int64_t result;
968
969 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
970 ogg_t *opriv = priv->opriv;
971
972 if (opriv->total_bytes > 0) {
973 if (priv->input_position + bytes_to_read > opriv->total_bytes)
974 bytes_to_read = opriv->total_bytes - priv->input_position;
975 if (bytes_to_read <= 0)
976 return 0;
977 }
978
979 ogg_sync_reset(&opriv->oy);
980 buf = ogg_sync_buffer(&(opriv->oy), bytes_to_read);
981
982 lseek64(opriv->fd, priv->input_position, SEEK_SET);
983 result = read(opriv->fd, (uint8_t *)buf, bytes_to_read);
984
985 opriv->page_valid = 0;
986
987 ogg_sync_wrote(&(opriv->oy), result);
988 return result;
989 }
990
991
992 /* Find the first first page between pos1 and pos2,
993 return file position, -1 is returned on failure. For theora only. */
994
find_first_page(lives_clip_data_t * cdata,int64_t pos1,int64_t pos2,int64_t * kframe,int64_t * frame)995 static int64_t find_first_page(lives_clip_data_t *cdata, int64_t pos1, int64_t pos2, int64_t *kframe, int64_t *frame) {
996 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
997
998 int64_t bytes;
999 long result;
1000
1001 ogg_t *opriv = priv->opriv;
1002
1003 int pages_checked = 0, page_packets_checked;
1004
1005 size_t bytes_to_read = pos2 - pos1 + 1;
1006
1007 int64_t granulepos;
1008
1009 // check index to see if pos1 is in index
1010
1011 // pull pages and check packets until we either reach the end or find a granulepos
1012
1013 priv->input_position = pos1;
1014
1015 //printf ("start %ld %ld\n",pos1,pos2);
1016
1017 seek_byte(cdata, pos1);
1018
1019 if (pos1 == priv->vstream->data_start) {
1020 /* set a dummy granulepos at data_start */
1021 *kframe = priv->kframe_offset;
1022 *frame = priv->kframe_offset;
1023
1024 opriv->page_valid = 1;
1025 return priv->input_position;
1026 }
1027
1028 if (bytes_to_read > BYTES_TO_READ) bytes_to_read = BYTES_TO_READ;
1029
1030 while (1) {
1031 if (priv->input_position >= pos2) {
1032 // we reached the end and found no pages
1033 //printf("exit a\n");
1034 *frame = -1;
1035 return -1;
1036 }
1037
1038 // read next chunk
1039 if (!(bytes = get_data(cdata, bytes_to_read))) {
1040 //printf("exit b\n");
1041 *frame = -1;
1042 return -1; // eof
1043 }
1044
1045 bytes_to_read = BYTES_TO_READ;
1046
1047 result = ogg_sync_pageseek(&opriv->oy, &opriv->current_page);
1048
1049 //printf("result is %ld\n",result);
1050
1051 if (result < 0) {
1052 // found a page, sync to page start
1053 priv->input_position -= result;
1054 pos1 = priv->input_position;
1055 continue;
1056 }
1057
1058 if (result > 0 || (result == 0 && opriv->oy.fill > 3 && !strncmp((char *)opriv->oy.data, "OggS", 4))) {
1059 pos1 = priv->input_position;
1060 break;
1061 }
1062
1063 priv->input_position += bytes;
1064 }
1065
1066 seek_byte(cdata, priv->input_position);
1067 ogg_stream_reset(&priv->vstream->stpriv->os);
1068
1069 while (1) {
1070 //printf("here %ld and %ld\n",priv->input_position,pos2);
1071
1072 if (priv->input_position >= pos2) {
1073 // reached the end of the search region and nothing was found
1074 *frame = -1;
1075 return priv->input_position; // we checked up to here
1076 }
1077
1078 //printf("a: checking page\n");
1079
1080 opriv->page_valid = 0;
1081
1082 if (!(result = get_page(cdata, priv->input_position))) {
1083 // EOF
1084 //printf("EOF ?\n");
1085 *frame = -1;
1086 return priv->input_position; // we checked up to here
1087 }
1088
1089 // found a page
1090 if (priv->vstream->stream_id != ogg_page_serialno(&(opriv->current_page))) {
1091 // page is not for this stream
1092 //printf("not for us\n");
1093 priv->input_position += result;
1094 if (!pages_checked) pos1 = priv->input_position;
1095 continue;
1096 }
1097
1098 ogg_stream_pagein(&priv->vstream->stpriv->os, &(opriv->current_page));
1099
1100 pages_checked++;
1101
1102 page_packets_checked = 0;
1103
1104 if (ogg_stream_packetout(&priv->vstream->stpriv->os, &opriv->op) > 0) {
1105 page_packets_checked++;
1106 }
1107
1108 if (page_packets_checked) {
1109 granulepos = ogg_page_granulepos(&(opriv->current_page));
1110 pthread_mutex_lock(&priv->idxc->mutex);
1111 theora_index_entry_add(cdata, granulepos, pos1);
1112 pthread_mutex_unlock(&priv->idxc->mutex);
1113
1114 *kframe =
1115 granulepos >> priv->vstream->stpriv->keyframe_granule_shift;
1116
1117 *frame = *kframe +
1118 granulepos - (*kframe << priv->vstream->stpriv->keyframe_granule_shift);
1119
1120 opriv->page_valid = 1;
1121 return pos1;
1122 }
1123
1124 // -> start of next page
1125 priv->input_position += result;
1126 }
1127 }
1128
1129
1130 /* Find the last frame for theora,
1131 -1 is returned on failure */
1132
find_last_theora_frame(lives_clip_data_t * cdata,lives_in_stream * vstream)1133 static int64_t find_last_theora_frame(lives_clip_data_t *cdata, lives_in_stream *vstream) {
1134 int64_t page_pos, start_pos;
1135 int64_t this_frame = 0, last_frame = -1;
1136 int64_t this_kframe = 0;
1137 int64_t pos1, pos2;
1138
1139 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1140 ogg_t *opriv = priv->opriv;
1141
1142 pos1 = vstream->data_start;
1143 pos2 = opriv->total_bytes;
1144 //serialno=vstream->stream_id;
1145
1146 start_pos = pos2 - BYTES_TO_READ;
1147
1148 while (1) {
1149 if (start_pos < pos1) start_pos = pos1;
1150
1151 //printf("in pos %ld and %ld with %ld\n",start_pos,pos2,vstream->data_start);
1152
1153 page_pos = find_first_page(cdata, start_pos, pos2, &this_kframe, &this_frame);
1154
1155 //printf("found page %ld %ld %ld\n",this_frame,last_frame,page_pos);
1156
1157 if (this_frame == -1) {
1158 // no pages found in range
1159 if (last_frame >= 0) { /* No more pages in range -> return last one */
1160 return last_frame;
1161 }
1162 if (start_pos <= pos1) {
1163 return -1;
1164 }
1165 /* Go back a bit */
1166 pos2 -= start_pos;
1167 start_pos -= BYTES_TO_READ;
1168 if (start_pos < pos1) start_pos = pos1;
1169 pos2 += start_pos;
1170 } else {
1171 // found a page, see if we can find another one
1172 //printf("set last_frame to %ld\n",this_frame);
1173 last_frame = this_frame;
1174 start_pos = page_pos + 1;
1175 }
1176 }
1177 return -1;
1178 }
1179
1180
1181 #ifdef HAVE_DIRAC
1182
1183 /* find first sync frame in a given file region. Return file offset. -1 is returned if no sync frame found.
1184 pos2 in not included in the search.
1185 This is for dirac only. */
1186
find_first_sync_frame(lives_clip_data_t * cdata,int64_t pos1,int64_t pos2,int64_t * frame)1187 static int64_t find_first_sync_frame(lives_clip_data_t *cdata, int64_t pos1, int64_t pos2, int64_t *frame) {
1188 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1189
1190 index_entry *idx = priv->idxc->idx;
1191 index_entry *extend = NULL;
1192
1193 int64_t bytes;
1194 long result;
1195
1196 ogg_t *opriv = priv->opriv;
1197 dirac_priv_t *dpriv = priv->dpriv;
1198
1199 int pages_checked = 0, page_packets_checked;
1200
1201 size_t bytes_to_read = pos2 - pos1 + 1;
1202
1203 // check index to see if pos1 is in index
1204
1205 while (idx != NULL) {
1206 if (idx->pagepos == pos1 && idx->value > -1) {
1207 // found !
1208 *frame = idx->value;
1209 return pos1;
1210 }
1211
1212 if (idx->pagepos < pos1 && idx->pagepos_end > pos1) {
1213
1214 // region was partly checked
1215 // continue from pagepos_end + 1
1216 pos1 = idx->pagepos_end + 1;
1217
1218 if (idx->pagepos_end >= pos2 - 1) {
1219 // region was checked and there are no seq frames
1220 *frame = -1;
1221 return pos1;
1222 }
1223
1224 break;
1225 }
1226
1227 if (idx->pagepos >= pos2) {
1228 // no entry found
1229 break;
1230 }
1231
1232 idx = idx->next;
1233 }
1234
1235 // pull pages and check packets until we either reach the end or find a sync point
1236
1237 priv->input_position = pos1;
1238
1239 ogg_stream_reset(&priv->vstream->stpriv->os);
1240
1241 //printf ("start %ld %ld\n",pos1,pos2);
1242
1243 seek_byte(cdata, pos1);
1244
1245 if (bytes_to_read > BYTES_TO_READ) bytes_to_read = BYTES_TO_READ;
1246
1247 while (1) {
1248 if (priv->input_position >= pos2) {
1249 // we reached the end and found no pages
1250 //printf("exit a\n");
1251 *frame = -1;
1252 return -1;
1253 }
1254
1255 // read next chunk
1256 if (!(bytes = get_data(cdata, bytes_to_read))) {
1257 //printf("exit b\n");
1258 *frame = -1;
1259 return -1; // eof
1260 }
1261
1262 bytes_to_read = BYTES_TO_READ;
1263
1264 result = ogg_sync_pageseek(&opriv->oy, &opriv->current_page);
1265
1266 //printf("result is %ld\n",result);
1267
1268 if (result < 0) {
1269 // found a page, sync to page start
1270 priv->input_position -= result;
1271 pos1 = priv->input_position;
1272 continue;
1273 }
1274
1275 if (result > 0 || (result == 0 && opriv->oy.fill > 3 && !strncmp((char *)opriv->oy.data, "OggS", 4))) {
1276 pos1 = priv->input_position;
1277 break;
1278 }
1279
1280 priv->input_position += bytes;
1281 }
1282
1283 seek_byte(cdata, priv->input_position);
1284 ogg_stream_reset(&priv->vstream->stpriv->os);
1285
1286 while (1) {
1287 //printf("here %ld and %ld\n",priv->input_position,pos2);
1288
1289 if (priv->input_position >= pos2) {
1290 //printf("exit 1 %ld %ld %ld\n",priv->input_position,result,pos2);
1291 // reached the end of the search region and nothing was found
1292 *frame = -1;
1293 return priv->input_position; // we checked up to here
1294 }
1295
1296 pthread_mutex_lock(&priv->idxc->mutex);
1297
1298 if ((idx = find_pagepos_in_index(priv->idxc->idx, priv->input_position)) != NULL) {
1299 // this part was already checked
1300
1301 //printf("WE ALREADY CHECKED THIS\n");
1302
1303 if (idx->value != -1) {
1304 // we already found a sync frame here
1305 if (extend != NULL) {
1306 extend->pagepos_end = idx->pagepos - 1;
1307 if (extend->pagepos_end < extend->pagepos) priv->idxc->idx = index_entry_delete(extend);
1308 }
1309
1310 *frame = idx->value;
1311 pthread_mutex_unlock(&priv->idxc->mutex);
1312 //printf("As I recall, the sync frame was %ld\n",*frame);
1313 return idx->pagepos;
1314 }
1315
1316 // no sync frame here - update this entry and jump to pagepos_end
1317 if (pages_checked >= 2 && idx->pagepos < pos1) idx->pagepos = pos1;
1318
1319 pos1 = priv->input_position = idx->pagepos_end + 1;
1320 pthread_mutex_unlock(&priv->idxc->mutex);
1321
1322 //printf("no seq frames, skipping\n");
1323
1324 // need more data
1325 ogg_stream_reset(&priv->vstream->stpriv->os);
1326
1327 continue;
1328 }
1329
1330 //printf("a: checking page\n");
1331
1332 opriv->page_valid = 0;
1333
1334 if (!(result = get_page(cdata, priv->input_position))) {
1335 // EOF
1336 //printf("EOF ?\n");
1337 *frame = -1;
1338 return priv->input_position; // we checked up to here
1339 }
1340
1341 // found a page
1342 if (priv->vstream->stream_id != ogg_page_serialno(&(opriv->current_page))) {
1343 // page is not for this stream
1344 //printf("not for us\n");
1345 priv->input_position += result;
1346 if (!pages_checked) pos1 = priv->input_position;
1347 continue;
1348 }
1349
1350 ogg_stream_pagein(&priv->vstream->stpriv->os, &(opriv->current_page));
1351
1352 if (pages_checked > 0) pages_checked++;
1353
1354 page_packets_checked = 0;
1355
1356 while (ogg_stream_packetout(&priv->vstream->stpriv->os, &opriv->op) > 0) {
1357 //printf("a checking packet %c %c %c %c %d\n",opriv->op.packet[0],opriv->op.packet[1],opriv->op.packet[2],opriv->op.packet[3],opriv->op.packet[4]);
1358
1359 page_packets_checked++;
1360
1361 // is this packet a seq start ?
1362 if (opriv->op.packet[4] == 0) {
1363 //printf("got a seq start\n");
1364
1365 // if other packets ended on this page, we know that seq start begins on this page
1366 // otherwise it will have begun at pos1
1367 if (page_packets_checked > 1) pos1 = priv->input_position;
1368
1369 // get the frame number, close extend, add a new index entry
1370 seek_byte(cdata, pos1);
1371
1372 // feed packets to the dirac_decoder until we get a frame number
1373 // note: in theory we should be able to get the next frame from the granulepos
1374 // however this seems broken
1375 priv->last_frame = -1;
1376 priv->cframe = -1;
1377
1378 ogg_data_process(cdata, NULL, FALSE);
1379
1380 //printf("seq frame was %ld\n",priv->last_frame);
1381
1382 *frame = priv->last_frame;
1383
1384 schro_decoder_reset(dpriv->schrodec);
1385
1386 ogg_stream_reset(&priv->vstream->stpriv->os);
1387
1388 pthread_mutex_lock(&priv->idxc->mutex);
1389 if (priv->last_frame > -1) {
1390 // finish off the previous search area
1391 if (extend) {
1392 extend->pagepos_end = pos1 - 1;
1393 if (extend->pagepos_end < extend->pagepos) priv->idxc->idx = index_entry_delete(extend);
1394 }
1395
1396 // and add this one
1397 extend = dirac_index_entry_add(cdata, pos1, priv->input_position + result - 1, *frame);
1398
1399 if (extend->pagepos_end < extend->pagepos) priv->idxc->idx = index_entry_delete(extend);
1400 else if (!extend->prev) priv->idxc->idx = extend;
1401
1402 } else {
1403 // we got no frames, we must have reached EOF
1404 if (extend) {
1405 extend->pagepos_end = priv->input_position - 1;
1406 if (extend->pagepos_end < extend->pagepos) priv->idxc->idx = index_entry_delete(extend);
1407 }
1408 pos1 = -1;
1409 }
1410 pthread_mutex_unlock(&priv->idxc->mutex);
1411
1412 return pos1; // return offset of start page
1413 }
1414 }
1415
1416 if (page_packets_checked > 0) {
1417 // we got some other kind of packet out, so a sequence header packet could only begin on this page
1418 pos1 = priv->input_position; // the start of this page
1419
1420 if (pages_checked == -1) {
1421 // we can start counting pages from here
1422 pages_checked = 1;
1423 }
1424
1425 if (pages_checked >= 2) {
1426 // if we checked from one packet to the next and found no seq header.
1427 // We now know that the first pages had no seq header
1428 // so we can start marking from pos1 up to start of this page - 1
1429 pthread_mutex_lock(&priv->idxc->mutex);
1430 if (!extend) {
1431 extend = dirac_index_entry_add(cdata, pos1, priv->input_position - 1, -1);
1432 if (!extend->prev) priv->idxc->idx = extend;
1433 } else {
1434 extend->pagepos_end = priv->input_position - 1;
1435 }
1436 if (extend->pagepos_end < extend->pagepos) priv->idxc->idx = index_entry_delete(extend);
1437 else if (extend->prev && extend->prev->pagepos_end == extend->pagepos - 1 && extend->prev->value == -1) {
1438 extend->prev->pagepos_end = extend->pagepos_end;
1439 index_entry_delete(extend);
1440 }
1441 pthread_mutex_unlock(&priv->idxc->mutex);
1442 }
1443 }
1444
1445 // -> start of next page
1446 priv->input_position += result;
1447 }
1448 }
1449
1450
1451 /* find last sync frame position in a given file region. Return file offset. -1 is returned if no sync frame found.
1452 This is for dirac only. */
1453
find_last_sync_frame(lives_clip_data_t * cdata,lives_in_stream * vstream)1454 static int64_t find_last_sync_frame(lives_clip_data_t *cdata, lives_in_stream *vstream) {
1455 int64_t page_pos, last_page_pos = -1, start_pos;
1456 int64_t this_frame = -1;
1457 int64_t pos1, pos2;
1458
1459 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1460 ogg_t *opriv = priv->opriv;
1461
1462 pos1 = vstream->data_start;
1463 pos2 = opriv->total_bytes;
1464 //serialno=vstream->stream_id;
1465
1466 start_pos = pos2 - BYTES_TO_READ;
1467
1468 while (1) {
1469 if (start_pos < pos1) start_pos = pos1;
1470
1471 page_pos = find_first_sync_frame(cdata, start_pos, pos2, &this_frame);
1472
1473 //printf("b found sync at %ld %ld\n",this_frame,page_pos);
1474
1475 if (this_frame == -1) {
1476 // no sync frames found in range
1477 if (last_page_pos >= 0) { /* No more pages in range -> return last one */
1478 return last_page_pos;
1479 }
1480 if (start_pos <= pos1) {
1481 return -1;
1482 }
1483 /* Go back a bit */
1484 pos2 -= start_pos;
1485 start_pos -= BYTES_TO_READ;
1486 if (start_pos < pos1) start_pos = pos1;
1487 pos2 += start_pos;
1488 } else {
1489 // found a page, see if we can find another one
1490 last_page_pos = page_pos;
1491 start_pos = page_pos + 1;
1492 }
1493 }
1494 return -1;
1495 }
1496
1497 #endif
1498
1499
get_last_granulepos(lives_clip_data_t * cdata,int serialno)1500 static int64_t get_last_granulepos(lives_clip_data_t *cdata, int serialno) {
1501 // granulepos here is actually a frame - TODO ** fix for audio !
1502
1503 #ifdef HAVE_DIRAC
1504 int64_t pos;
1505 #endif
1506 lives_in_stream *stream;
1507
1508 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1509
1510 int64_t frame;
1511
1512 stream = stream_from_sno(cdata, serialno);
1513 if (!stream) return -1;
1514
1515 #ifdef HAVE_DIRAC
1516 if (stream->stpriv->fourcc_priv == FOURCC_DIRAC) {
1517 dirac_priv_t *dpriv = priv->dpriv;
1518
1519 pos = find_last_sync_frame(cdata, priv->vstream);
1520 seek_byte(cdata, pos);
1521
1522 ogg_stream_reset(&priv->vstream->stpriv->os);
1523
1524 schro_decoder_reset(dpriv->schrodec);
1525
1526 priv->last_frame = -1;
1527 priv->cframe = -1;
1528
1529 ogg_data_process(cdata, NULL, FALSE); // read pages from last sync frame
1530
1531 while (ogg_data_process(cdata, NULL, TRUE)); // continue until we reach EOF
1532
1533 schro_decoder_reset(dpriv->schrodec);
1534
1535 ogg_stream_reset(&priv->vstream->stpriv->os);
1536
1537 //printf("last dirac frame is %ld, adjust to %ld\n",priv->last_frame, priv->last_frame-priv->kframe_offset);
1538
1539 priv->last_frame -= priv->kframe_offset;
1540
1541 return priv->last_frame;
1542 }
1543 #endif
1544
1545 // TODO - fix for vorbis
1546
1547 frame = find_last_theora_frame(cdata, priv->vstream);
1548 if (frame < 0) return -1;
1549
1550 return frame;
1551 }
1552
1553
granulepos_2_time(lives_in_stream * s,int64_t pos)1554 static double granulepos_2_time(lives_in_stream *s, int64_t pos) {
1555 // actually should be frame or sample to time
1556
1557 int64_t frames;
1558 stream_priv_t *stream_priv = (stream_priv_t *)(s->stpriv);
1559
1560 switch (stream_priv->fourcc_priv) {
1561 case FOURCC_VORBIS:
1562 //fprintf(stderr,"apos is %lld\n",pos);
1563 return ((long double)pos / (long double)s->samplerate);
1564 break;
1565 case FOURCC_THEORA:
1566 case FOURCC_DIRAC:
1567 //fprintf(stderr,"vpos is %lld\n",pos);
1568 stream_priv = (stream_priv_t *)(s->stpriv);
1569
1570 frames = pos;
1571
1572 return ((double)s->fps_denom / (double)s->fps_num * (double)frames);
1573 break;
1574 }
1575 return -1;
1576 }
1577
1578
stream_peek(int fd,char * str,size_t len)1579 static ssize_t stream_peek(int fd, char *str, size_t len) {
1580 off_t cpos = lseek(fd, 0, SEEK_CUR); // get current posn
1581
1582 #ifndef IS_MINGW
1583 return pread(fd, str, len, cpos); // read len bytes without changing cpos
1584 #else
1585 ssize_t ret = read(fd, str, len);
1586 lseek(fd, cpos, SEEK_SET);
1587 return ret;
1588 #endif
1589 }
1590
1591
open_ogg(lives_clip_data_t * cdata)1592 static int open_ogg(lives_clip_data_t *cdata) {
1593 char scheck[4];
1594
1595 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1596 ogg_t *opriv = priv->opriv;
1597
1598 if (stream_peek(opriv->fd, scheck, 4) < 4) return 0;
1599
1600 if (strncmp(scheck, "OggS", 4)) return 0;
1601
1602 ogg_sync_init(&(opriv->oy));
1603
1604 /* Set up the tracks */
1605 if (!setup_tracks(cdata)) {
1606 ogg_sync_clear(&opriv->oy);
1607 return 0;
1608 }
1609
1610 return 1;
1611 }
1612
1613
attach_stream(lives_clip_data_t * cdata,boolean isclone)1614 static boolean attach_stream(lives_clip_data_t *cdata, boolean isclone) {
1615 // open the file and get a handle
1616
1617 struct stat sb;
1618
1619 int64_t gpos;
1620
1621 double stream_duration;
1622
1623 boolean is_partial_clone = FALSE;
1624
1625 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1626 ogg_t *opriv = priv->opriv = (ogg_t *)malloc(sizeof(ogg_t));
1627
1628 register int i;
1629
1630 if ((opriv->fd = open(cdata->URI, O_RDONLY)) == -1) {
1631 fprintf(stderr, "ogg_theora_decoder: unable to open %s\n", cdata->URI);
1632 free(opriv);
1633 priv->opriv = NULL;
1634 return FALSE;
1635 }
1636
1637 #ifdef IS_MINGW
1638 setmode(opriv->fd, O_BINARY);
1639 #endif
1640
1641 if (isclone && !priv->inited) {
1642 isclone = FALSE;
1643 if (cdata->fps > 0. && cdata->nframes > 0)
1644 is_partial_clone = TRUE;
1645 }
1646
1647 if (!isclone) {
1648 stat(cdata->URI, &sb);
1649 opriv->total_bytes = sb.st_size;
1650 }
1651
1652 opriv->page_valid = 0;
1653
1654 // index init
1655 priv->idxc = idxc_for(cdata);
1656
1657 /* get ogg info */
1658 if (!open_ogg(cdata)) {
1659 close(opriv->fd);
1660 free(opriv);
1661 priv->opriv = NULL;
1662 return FALSE;
1663 }
1664
1665 priv->last_kframe = 10000000;
1666 priv->last_frame = 100000000;
1667 priv->inited = TRUE;
1668
1669 #ifdef HAVE_THEORA
1670 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
1671 // theora only
1672 int i;
1673 ogg_packet op;
1674 uint8_t *ext_pos;
1675 theora_priv_t *tpriv = priv->tpriv = (theora_priv_t *)malloc(sizeof(theora_priv_t));
1676
1677 /* Initialize theora structures */
1678 theora_info_init(&tpriv->ti);
1679 theora_comment_init(&tpriv->tc);
1680
1681 /* Get header packets and initialize decoder */
1682 if (priv->vstream->ext_data == NULL) {
1683 fprintf(stderr, "Theora codec requires extra data\n");
1684 close(opriv->fd);
1685 free(opriv);
1686 priv->opriv = NULL;
1687 free(tpriv);
1688 priv->tpriv = NULL;
1689 return FALSE;
1690 }
1691
1692 ext_pos = priv->vstream->ext_data;
1693
1694 for (i = 0; i < 3; i++) {
1695 ext_pos = ptr_2_op(ext_pos, &op);
1696 theora_decode_header(&tpriv->ti, &tpriv->tc, &op);
1697 }
1698
1699 theora_decode_init(&tpriv->ts, &tpriv->ti);
1700
1701 // check to find whether first frame is zero or one
1702 // if version >= 3.2.1 first kframe is 1; otherwise 0
1703 if (priv->vstream->version >= 3002001) priv->kframe_offset = 1;
1704 else priv->kframe_offset = 0;
1705 }
1706 #endif
1707
1708 #ifdef HAVE_DIRAC
1709 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
1710 // dirac only
1711 dirac_priv_t *dpriv = priv->dpriv = (dirac_priv_t *)malloc(sizeof(dirac_priv_t));
1712
1713 schro_init();
1714
1715 dpriv->schroframe = NULL;
1716
1717 if ((dpriv->schrodec = schro_decoder_new()) == NULL) {
1718 fprintf(stderr, "Failed to init schro decoder\n");
1719 close(opriv->fd);
1720 free(opriv);
1721 priv->opriv = NULL;
1722 free(dpriv);
1723 priv->dpriv = NULL;
1724 return FALSE;
1725 }
1726 //schro_debug_set_level(SCHRO_LEVEL_WARNING);
1727 schro_debug_set_level(0);
1728 }
1729 #endif
1730
1731 if (isclone) return TRUE;
1732
1733 cdata->nclips = 1;
1734
1735 // video part
1736 cdata->interlace = LIVES_INTERLACE_NONE;
1737
1738 cdata->par = 1.;
1739
1740 // TODO
1741 cdata->offs_x = 0;
1742 cdata->offs_y = 0;
1743 cdata->frame_gamma = WEED_GAMMA_UNKNOWN;
1744 cdata->frame_width = cdata->width;
1745 cdata->frame_height = cdata->height;
1746
1747 cdata->YUV_clamping = WEED_YUV_CLAMPING_CLAMPED;
1748 cdata->YUV_subspace = WEED_YUV_SUBSPACE_YCBCR;
1749 cdata->YUV_sampling = WEED_YUV_SAMPLING_DEFAULT;
1750
1751 /* Get format */
1752
1753 #ifdef HAVE_THEORA
1754 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
1755 theora_priv_t *tpriv = priv->tpriv;
1756 cdata->width = cdata->frame_width = opriv->y_width = tpriv->ti.frame_width;
1757 cdata->height = cdata->frame_height = opriv->y_height = tpriv->ti.frame_height;
1758
1759 if (cdata->fps == 0.) cdata->fps = (float)tpriv->ti.fps_numerator / (float)tpriv->ti.fps_denominator;
1760
1761 switch (tpriv->ti.pixelformat) {
1762 case OC_PF_420:
1763 cdata->palettes[0] = WEED_PALETTE_YUV420P;
1764 opriv->uv_width = opriv->y_width >> 1;
1765 break;
1766 case OC_PF_422:
1767 cdata->palettes[0] = WEED_PALETTE_YUV422P;
1768 opriv->uv_width = opriv->y_width >> 1;
1769 break;
1770 case OC_PF_444:
1771 cdata->palettes[0] = WEED_PALETTE_YUV444P;
1772 opriv->uv_width = opriv->y_width;
1773 break;
1774 default:
1775 fprintf(stderr, "Unknown pixelformat %d", tpriv->ti.pixelformat);
1776 return FALSE;
1777 }
1778
1779 cdata->palettes[1] = WEED_PALETTE_END;
1780 cdata->current_palette = cdata->palettes[0];
1781 sprintf(cdata->video_name, "%s", "theora");
1782
1783 if (tpriv->tc.comments > 0) {
1784 size_t lenleft = 256, csize;
1785 char *cbuf = cdata->comment;
1786 for (i = 0; i <= tpriv->tc.comments; i++) {
1787 csize = tpriv->tc.comment_lengths[i];
1788 if (csize > lenleft) csize = lenleft;
1789 snprintf(cbuf, csize, "%s", tpriv->tc.user_comments[i]);
1790 cbuf += csize;
1791 lenleft -= csize;
1792 if (lenleft == 0) break;
1793 if (i + 1 <= tpriv->tc.comments) {
1794 if (lenleft < strlen("\n") + 1) break;
1795 sprintf(cbuf, "\n");
1796 cbuf += strlen("\n");
1797 lenleft -= strlen("\n");
1798 }
1799 }
1800 }
1801
1802 }
1803 #endif
1804
1805 #ifdef HAVE_DIRAC
1806 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
1807 // feed some pages to the decoder so it gets the idea
1808 dirac_priv_t *dpriv = priv->dpriv;
1809 int64_t start_pos = priv->input_position;
1810
1811 seek_byte(cdata, priv->vstream->data_start);
1812
1813 while (1) {
1814 int64_t input_pos;
1815 boolean done = FALSE;
1816
1817 opriv->page_valid = 0;
1818
1819 if (!(input_pos = get_page(cdata, priv->input_position))) {
1820 // should never reach here
1821 fprintf(stderr, "EOF1 while decoding\n");
1822 return FALSE;
1823 }
1824
1825 priv->input_position += input_pos;
1826
1827 if (ogg_page_serialno(&(opriv->current_page)) != priv->vstream->stream_id) continue;
1828 ogg_stream_pagein(&priv->vstream->stpriv->os, &(opriv->current_page));
1829
1830 while (ogg_stream_packetout(&priv->vstream->stpriv->os, &opriv->op) > 0) {
1831 // feed packets to decoder
1832 SchroBuffer *schrobuffer;
1833 int state;
1834
1835 schrobuffer = schro_buffer_new_with_data(opriv->op.packet, opriv->op.bytes);
1836 schro_decoder_autoparse_push(dpriv->schrodec, schrobuffer);
1837
1838 state = schro_decoder_autoparse_wait(dpriv->schrodec);
1839
1840 if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) {
1841 // should have our cdata now
1842 get_dirac_cdata(cdata, dpriv->schrodec);
1843 done = TRUE;
1844 break;
1845 }
1846 if (done) break;
1847 }
1848 if (done) break;
1849 }
1850
1851 cdata->current_palette = cdata->palettes[0];
1852
1853 // reset and seek back to start
1854 //fprintf(stderr,"got dirac fps=%.4f %d x %d\n",cdata->fps,cdata->width,cdata->height);
1855
1856 schro_decoder_reset(dpriv->schrodec);
1857 seek_byte(cdata, start_pos);
1858 ogg_stream_reset(&priv->vstream->stpriv->os);
1859
1860 // find first keyframe
1861 find_first_sync_frame(cdata, priv->vstream->data_start, opriv->total_bytes, &priv->kframe_offset);
1862
1863 sprintf(cdata->video_name, "%s", "dirac");
1864 }
1865
1866 #endif
1867
1868 sprintf(cdata->container_name, "%s", "ogg");
1869
1870 // audio part
1871 cdata->asigned = FALSE;
1872 cdata->achans = 0;
1873 cdata->ainterleaf = TRUE;
1874 cdata->asamps = 0;
1875
1876 if (priv->astream) {
1877 sprintf(cdata->audio_name, "%s", "vorbis");
1878 } else memset(cdata->audio_name, 0, 1);
1879
1880 if (isclone) return TRUE;
1881
1882 // get duration
1883
1884 if (priv->astream) {
1885 ogg_stream_reset(&priv->astream->stpriv->os);
1886 gpos = get_last_granulepos(cdata, priv->astream->stream_id);
1887 stream_duration =
1888 granulepos_2_time(priv->astream, gpos);
1889 priv->astream->duration = stream_duration;
1890 priv->astream->stpriv->last_granulepos = gpos;
1891 //printf("priv->astream duration is %.4f\n",stream_duration);
1892 }
1893
1894 if (priv->vstream != NULL) {
1895 ogg_stream_reset(&priv->vstream->stpriv->os);
1896 gpos = get_last_granulepos(cdata, priv->vstream->stream_id);
1897
1898 /* kframe=gpos >> priv->vstream->priv->keyframe_granule_shift;
1899 priv->vstream->nframes = kframe + gpos-(kframe<<priv->vstream->priv->keyframe_granule_shift);*/
1900
1901 priv->vstream->nframes = gpos;
1902
1903 stream_duration =
1904 granulepos_2_time(priv->vstream, gpos);
1905 priv->vstream->duration = stream_duration;
1906 priv->vstream->stpriv->last_granulepos = gpos;
1907 //printf("priv->vstream duration is %.4f %ld\n",stream_duration,priv->vstream->nframes);
1908 }
1909
1910 if (is_partial_clone) return TRUE;
1911
1912 cdata->nframes = priv->vstream->nframes;
1913
1914 if (cdata->width != cdata->frame_width || cdata->height != cdata->frame_height)
1915 fprintf(stderr, "ogg_decoder: info - frame size=%d x %d, pixel size=%d x %d\n", cdata->frame_width, cdata->frame_height,
1916 cdata->width,
1917 cdata->height);
1918
1919 return TRUE;
1920 }
1921
1922
detach_stream(lives_clip_data_t * cdata)1923 static void detach_stream(lives_clip_data_t *cdata) {
1924 // close the file, free the decoder
1925 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1926 ogg_t *opriv = priv->opriv;
1927
1928 #ifdef HAVE_DIRAC
1929 dirac_priv_t *dpriv = priv->dpriv;
1930 #endif
1931
1932 close(opriv->fd);
1933
1934 ogg_sync_clear(&opriv->oy);
1935
1936 #ifdef HAVE_THEORA
1937 if (priv->tpriv) {
1938 // theora only
1939 // TODO - call function in decoder
1940 theora_priv_t *tpriv = priv->tpriv;
1941 theora_clear(&tpriv->ts);
1942 theora_comment_clear(&tpriv->tc);
1943 theora_info_clear(&tpriv->ti);
1944 free(tpriv);
1945 priv->tpriv = NULL;
1946 }
1947 #endif
1948
1949 #ifdef HAVE_DIRAC
1950 if (priv->dpriv) {
1951 schro_decoder_reset(dpriv->schrodec);
1952 if (dpriv->schroframe != NULL) {
1953 schro_frame_unref(dpriv->schroframe);
1954 }
1955 if (dpriv->schrodec != NULL) schro_decoder_free(dpriv->schrodec);
1956 dpriv->schrodec = NULL;
1957 dpriv->schroframe = NULL;
1958 free(dpriv);
1959 priv->dpriv = NULL;
1960 }
1961 #endif
1962
1963 // free stream data
1964 if (priv->astream) {
1965 if (priv->astream->ext_data != NULL) free(priv->astream->ext_data);
1966 ogg_stream_clear(&priv->astream->stpriv->os);
1967 free(priv->astream->stpriv);
1968 free(priv->astream);
1969 priv->astream = NULL;
1970 }
1971
1972 if (priv->vstream) {
1973 if (priv->vstream->ext_data != NULL) free(priv->vstream->ext_data);
1974 ogg_stream_clear(&priv->vstream->stpriv->os);
1975 free(priv->vstream->stpriv);
1976 free(priv->vstream);
1977 priv->vstream = NULL;
1978 }
1979
1980 if (cdata->palettes) free(cdata->palettes);
1981 cdata->palettes = NULL;
1982 }
1983
1984
frame_to_gpos(lives_clip_data_t * cdata,int64_t kframe,int64_t frame)1985 static inline int64_t frame_to_gpos(lives_clip_data_t *cdata, int64_t kframe, int64_t frame) {
1986 // this is only valid for theora; for dirac there is no unique gpos for a particular frame
1987 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
1988 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
1989 return kframe;
1990 }
1991 return (kframe << priv->vstream->stpriv->keyframe_granule_shift) + (frame - kframe);
1992 }
1993
1994
ogg_seek(lives_clip_data_t * cdata,int64_t tframe,int64_t ppos_lower,int64_t ppos_upper,boolean can_exact)1995 static int64_t ogg_seek(lives_clip_data_t *cdata, int64_t tframe, int64_t ppos_lower, int64_t ppos_upper, boolean can_exact) {
1996 // for theora:
1997
1998 // we do two passes here, first with can_exact set, then with can_exact unset
1999
2000 // if can_exact is set, we find the granulepos nearest to or including the target granulepos
2001 // from this we extract an estimate of the keyframe (but note that there could be other keyframes between the found granulepos and the target)
2002
2003 // on the second pass we find the highest granulepos < target. This places us just before or at the start of the target keyframe
2004
2005 // when we come to decode, we start from this second position, discarding any completed packets on that page,
2006 // and read pages discarding packets until we get to the target frame
2007
2008 // we return the granulepos which we find
2009
2010 // for dirac:
2011
2012 // we find the highest sync frame <= target frame, and return the sync_frame number
2013 // can_exact should be set to TRUE
2014
2015 // the method used is bi-sections
2016 // first we divided the region into two, then we check the first keyframe of the upper part
2017 // if this is == target we return
2018 // if > target, or we find no keyframes, we go to the lower segment
2019 // this is then repeated until the segment size is too small to hold a packet, at which point we return our best
2020 // match
2021
2022 int64_t start_pos, end_pos, pagepos = -1;
2023 int64_t frame, kframe, segsize;
2024
2025 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2026 ogg_t *opriv = priv->opriv;
2027
2028 int64_t best_kframe = -1;
2029 int64_t best_frame = -1;
2030 int64_t best_pagepos = -1;
2031
2032 //fprintf(stderr,"seek to frame %ld %d\n",tframe,can_exact);
2033
2034 if (tframe < priv->kframe_offset) {
2035 priv->cpagepos = priv->vstream->data_start;
2036 if (!can_exact) {
2037 seek_byte(cdata, priv->vstream->data_start);
2038 return frame_to_gpos(cdata, priv->kframe_offset, 1);
2039 }
2040 return frame_to_gpos(cdata, priv->kframe_offset, 0);
2041 }
2042
2043 if (ppos_lower < 0) ppos_lower = priv->vstream->data_start;
2044 if (ppos_upper < 0) ppos_upper = opriv->total_bytes;
2045 if (ppos_upper > opriv->total_bytes) ppos_upper = opriv->total_bytes;
2046
2047 start_pos = ppos_lower;
2048 end_pos = ppos_upper;
2049
2050 segsize = (end_pos - start_pos + 1) >> 1;
2051
2052 do {
2053 // see if the frame lies in current segment
2054
2055 if (start_pos < ppos_lower) start_pos = ppos_lower;
2056 if (end_pos > ppos_upper) end_pos = ppos_upper;
2057
2058 if (start_pos >= end_pos) {
2059 if (start_pos == ppos_lower) {
2060 if (!can_exact) seek_byte(cdata, start_pos);
2061 priv->cpagepos = start_pos;
2062 return frame_to_gpos(cdata, priv->kframe_offset, 1);
2063 }
2064 break;
2065 }
2066
2067 //fprintf(stderr,"check seg %ld to %ld for %ld\n",start_pos,end_pos,tframe);
2068
2069 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) pagepos = find_first_page(cdata, start_pos, end_pos, &kframe, &frame);
2070 #ifdef HAVE_DIRAC
2071 else {
2072 pagepos = find_first_sync_frame(cdata, start_pos, end_pos, &kframe);
2073 frame = kframe;
2074 }
2075 #endif
2076 if (pagepos != -1 && kframe != -1) {
2077 // found a keyframe
2078
2079 //fprintf(stderr,"first sync_frame is %ld %ld\n",kframe,frame);
2080
2081 if (can_exact && frame >= tframe && kframe <= tframe) {
2082 // got it !
2083 //fprintf(stderr,"seek got keyframe %ld for %ld\n",kframe,tframe);
2084 priv->cpagepos = pagepos;
2085 return frame_to_gpos(cdata, kframe, frame);
2086 }
2087
2088 if ((kframe < tframe || (can_exact && kframe == tframe)) && kframe > best_kframe) {
2089 best_kframe = kframe;
2090 best_frame = frame;
2091 best_pagepos = pagepos;
2092 }
2093
2094 if (frame >= tframe) {
2095 //fprintf(stderr,"checking lower segment\n");
2096 // check previous segment
2097 start_pos -= segsize;
2098 end_pos -= segsize;
2099 } else start_pos = pagepos;
2100 }
2101
2102 // no keyframe found, check lower segment
2103 else {
2104 //fprintf(stderr,"no keyframe, checking lower segment\n");
2105 end_pos -= segsize;
2106 start_pos -= segsize;
2107 }
2108
2109 segsize = (end_pos - start_pos + 1) >> 1;
2110 start_pos += segsize;
2111 } while (segsize > 64);
2112
2113 if (best_kframe > -1) {
2114 int64_t gpos = frame_to_gpos(cdata, best_kframe, tframe);
2115 //fprintf(stderr,"seek2 got keyframe %ld %ld\n",best_kframe,best_frame);
2116 if (!can_exact) seek_byte(cdata, best_pagepos);
2117 priv->cpagepos = best_pagepos;
2118 // TODO - add to vlc
2119 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2120 pthread_mutex_lock(&priv->idxc->mutex);
2121 theora_index_entry_add((lives_clip_data_t *)cdata, gpos, priv->cpagepos);
2122 pthread_mutex_unlock(&priv->idxc->mutex);
2123 }
2124 gpos = frame_to_gpos(cdata, best_kframe, best_frame);
2125 return gpos;
2126 }
2127
2128 // should never reach here
2129 //fprintf(stderr,"not found\n");
2130 return -1;
2131 }
2132
2133
2134 //////////////////////////////////////////
2135 // std functions
2136
version(void)2137 const char *version(void) {
2138 return plugin_version;
2139 }
2140
2141
module_check_init(void)2142 const char *module_check_init(void) {
2143 indices = NULL;
2144 nidxc = 0;
2145 pthread_mutex_init(&indices_mutex, NULL);
2146 return NULL;
2147 }
2148
2149
init_cdata(lives_clip_data_t * data)2150 lives_clip_data_t *init_cdata(lives_clip_data_t *data) {
2151 lives_clip_data_t *cdata;
2152
2153 if (!data) {
2154 cdata = cdata_new(NULL);
2155 cdata_stamp(cdata, plname, vmaj, vmin);
2156 cdata->palettes = malloc(4 * sizeof(int));
2157 cdata->palettes[3] = WEED_PALETTE_END;
2158 } else cdata = data;
2159
2160 cdata->priv = calloc(1, sizeof(lives_ogg_priv_t));
2161
2162 cdata->interlace = LIVES_INTERLACE_NONE;
2163 cdata->frame_gamma = WEED_GAMMA_UNKNOWN;
2164
2165 return cdata;
2166 }
2167
2168
ogg_clone(lives_clip_data_t * cdata)2169 static lives_clip_data_t *ogg_clone(lives_clip_data_t *cdata) {
2170 lives_clip_data_t *clone = clone_cdata(cdata);
2171 lives_ogg_priv_t *dpriv, *spriv;
2172
2173 cdata_stamp(clone, plname, vmaj, vmin);
2174
2175 // create "priv" elements
2176 spriv = cdata->priv;
2177
2178 if (spriv) {
2179 clone->priv = dpriv = (lives_ogg_priv_t *)calloc(1, sizeof(lives_ogg_priv_t));
2180 dpriv->inited = TRUE;
2181 } else {
2182 clone = init_cdata(clone);
2183 dpriv = clone->priv;
2184 }
2185
2186 if (!clone->palettes) {
2187 clone->palettes = malloc(2 * sizeof(int));
2188 clone->palettes[1] = WEED_PALETTE_END;
2189 }
2190
2191 if (!attach_stream(clone, TRUE)) {
2192 clip_data_free(clone);
2193 return NULL;
2194 }
2195
2196 // create "priv" elements
2197 dpriv = clone->priv;
2198 spriv = cdata->priv;
2199
2200 if (!attach_stream(clone, TRUE)) {
2201 clip_data_free(clone);
2202 return NULL;
2203 }
2204
2205 if (spriv) {
2206 ogg_t *sopriv = spriv->opriv;
2207 ogg_t *dopriv = dpriv->opriv;
2208 dpriv->inited = TRUE;
2209 dopriv->total_bytes = sopriv->total_bytes;
2210 ogg_stream_reset(&dpriv->astream->stpriv->os);
2211 dpriv->astream->duration = spriv->astream->duration;
2212 dpriv->astream->stpriv->last_granulepos = spriv->astream->stpriv->last_granulepos;
2213
2214 ogg_stream_reset(&dpriv->vstream->stpriv->os);
2215 dpriv->vstream->nframes = spriv->vstream->nframes;
2216 dpriv->vstream->duration = spriv->vstream->duration;
2217 dpriv->vstream->stpriv->last_granulepos = spriv->vstream->stpriv->last_granulepos;
2218 } else {
2219 clone->nclips = 1;
2220
2221 ///////////////////////////////////////////////////////////
2222
2223 sprintf(clone->container_name, "%s", "mkv");
2224
2225 // clone->height was set when we attached the stream
2226
2227 if (clone->frame_width == 0 || clone->frame_width < clone->width) clone->frame_width = clone->width;
2228 else {
2229 clone->offs_x = (clone->frame_width - clone->width) / 2;
2230 }
2231
2232 if (clone->frame_height == 0 || clone->frame_height < clone->height) clone->frame_height = clone->height;
2233 else {
2234 clone->offs_y = (clone->frame_height - clone->height) / 2;
2235 }
2236
2237 clone->frame_width = clone->width + clone->offs_x * 2;
2238 clone->frame_height = clone->height + clone->offs_y * 2;
2239
2240 ////////////////////////////////////////////////////////////////////
2241
2242 clone->asigned = TRUE;
2243 clone->ainterleaf = TRUE;
2244 }
2245
2246 dpriv->last_frame = -1;
2247
2248 return clone;
2249 }
2250
2251
get_clip_data(const char * URI,lives_clip_data_t * cdata)2252 lives_clip_data_t *get_clip_data(const char *URI, lives_clip_data_t *cdata) {
2253 // the first time this is called, caller should pass NULL as the clone
2254 // subsequent calls to this should re-use the same cdata
2255
2256 // if the host wants a different URI, a different current_clip, or a different current_palette,
2257 // this must be called again with the same
2258 // cdata as the second parameter
2259 lives_ogg_priv_t *priv;
2260
2261 if (!URI && cdata) {
2262 // create a clone of cdata - we also need to be able to handle a "fake" clone with only
2263 // URI, nframes and fps set (URI == NULL)
2264 return ogg_clone(cdata);
2265 }
2266
2267 if (cdata && cdata->current_clip > 0) {
2268 // currently we only support one clip per container
2269 clip_data_free(cdata);
2270 return NULL;
2271 }
2272
2273 if (!cdata) {
2274 cdata = init_cdata(NULL);
2275 }
2276
2277 priv = (lives_ogg_priv_t *)cdata->priv;
2278
2279 if (!cdata->URI || strcmp(URI, cdata->URI)) {
2280 if (cdata->URI) {
2281 detach_stream(cdata);
2282 free(cdata->URI);
2283 }
2284 cdata->URI = strdup(URI);
2285 if (!attach_stream(cdata, FALSE)) {
2286 free(cdata->URI);
2287 cdata->URI = NULL;
2288 clip_data_free(cdata);
2289 return NULL;
2290 }
2291 cdata->current_clip = 0;
2292 }
2293
2294 if (!priv->vstream) {
2295 clip_data_free(cdata);
2296 return NULL;
2297 }
2298
2299 cdata->nclips = 1;
2300
2301 ///////////////////////////////////////////////////////////
2302
2303 sprintf(cdata->container_name, "%s", "ogg");
2304
2305 // cdata->height was set when we attached the stream
2306
2307 if (cdata->frame_width == 0 || cdata->frame_width < cdata->width) cdata->frame_width = cdata->width;
2308 else {
2309 cdata->offs_x = (cdata->frame_width - cdata->width) / 2;
2310 }
2311
2312 if (cdata->frame_height == 0 || cdata->frame_height < cdata->height) cdata->frame_height = cdata->height;
2313 else {
2314 cdata->offs_y = (cdata->frame_height - cdata->height) / 2;
2315 }
2316
2317 cdata->frame_width = cdata->width + cdata->offs_x * 2;
2318 cdata->frame_height = cdata->height + cdata->offs_y * 2;
2319
2320 ////////////////////////////////////////////////////////////////////
2321
2322 cdata->asigned = TRUE;
2323 cdata->ainterleaf = TRUE;
2324
2325 return cdata;
2326 }
2327
2328
2329 #ifdef HAVE_THEORA
2330
ogg_theora_read(lives_clip_data_t * cdata,ogg_packet * op,yuv_buffer * yuv)2331 static boolean ogg_theora_read(lives_clip_data_t *cdata, ogg_packet *op, yuv_buffer *yuv) {
2332 // this packet is for our theora decoder
2333 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2334 theora_priv_t *tpriv = priv->tpriv;
2335
2336 //printf("skip is %d\n",priv->skip);
2337
2338 if (theora_decode_packetin(&tpriv->ts, op) == 0) {
2339 if (priv->skip <= 0) {
2340 if (theora_decode_YUVout(&tpriv->ts, yuv) == 0) {
2341 priv->frame_out = TRUE;
2342 }
2343 }
2344 }
2345 return priv->frame_out;
2346 }
2347
2348
write_black_pixel(unsigned char * idst,int pal,int npixels,int y_black)2349 static size_t write_black_pixel(unsigned char *idst, int pal, int npixels, int y_black) {
2350 unsigned char *dst = idst;
2351 register int i;
2352
2353 for (i = 0; i < npixels; i++) {
2354 switch (pal) {
2355 case WEED_PALETTE_RGBA32:
2356 case WEED_PALETTE_BGRA32:
2357 dst[0] = dst[1] = dst[2] = 0;
2358 dst[3] = 255;
2359 dst += 4;
2360 break;
2361 case WEED_PALETTE_ARGB32:
2362 dst[1] = dst[2] = dst[3] = 0;
2363 dst[0] = 255;
2364 dst += 4;
2365 break;
2366 case WEED_PALETTE_UYVY8888:
2367 dst[1] = dst[3] = y_black;
2368 dst[0] = dst[2] = 128;
2369 dst += 4;
2370 break;
2371 case WEED_PALETTE_YUYV8888:
2372 dst[0] = dst[2] = y_black;
2373 dst[1] = dst[3] = 128;
2374 dst += 4;
2375 break;
2376 case WEED_PALETTE_YUV888:
2377 dst[0] = y_black;
2378 dst[1] = dst[2] = 128;
2379 dst += 3;
2380 break;
2381 case WEED_PALETTE_YUVA8888:
2382 dst[0] = y_black;
2383 dst[1] = dst[2] = 128;
2384 dst[3] = 255;
2385 dst += 4;
2386 break;
2387 case WEED_PALETTE_YUV411:
2388 dst[0] = dst[3] = 128;
2389 dst[1] = dst[2] = dst[4] = dst[5] = y_black;
2390 dst += 6;
2391 default:
2392 break;
2393 }
2394 }
2395 return idst - dst;
2396 }
2397 #endif
2398
2399
2400 #ifdef HAVE_DIRAC
2401
schroframe_to_pixel_data(SchroFrame * sframe,uint8_t ** pixel_data)2402 static void schroframe_to_pixel_data(SchroFrame *sframe, uint8_t **pixel_data) {
2403 uint8_t *s_y = sframe->components[0].data;
2404 uint8_t *s_u = sframe->components[1].data;
2405 uint8_t *s_v = sframe->components[2].data;
2406
2407 uint8_t *d_y = pixel_data[0];
2408 uint8_t *d_u = pixel_data[1];
2409 uint8_t *d_v = pixel_data[2];
2410
2411 register int i;
2412
2413 boolean crow = FALSE;
2414
2415 int mheight = (sframe->components[0].height >> 1) << 1;
2416
2417 for (i = 0; i < mheight; i++) {
2418 memcpy(d_y, s_y, sframe->components[0].width);
2419 d_y += sframe->components[0].width;
2420 s_y += sframe->components[0].stride;
2421 if (sframe->components[1].height == sframe->components[0].height || crow) {
2422 memcpy(d_u, s_u, sframe->components[1].width);
2423 memcpy(d_v, s_v, sframe->components[2].width);
2424 d_u += sframe->components[1].width;
2425 d_v += sframe->components[2].width;
2426 s_u += sframe->components[1].stride;
2427 s_v += sframe->components[2].stride;
2428 }
2429 crow = !crow;
2430 sched_yield();
2431 }
2432 }
2433
2434
ogg_dirac_read(lives_clip_data_t * cdata,ogg_packet * op,uint8_t ** pixel_data,boolean cont)2435 static int64_t ogg_dirac_read(lives_clip_data_t *cdata, ogg_packet *op, uint8_t **pixel_data, boolean cont) {
2436 // this packet is for our dirac decoder
2437 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2438 dirac_priv_t *dpriv = priv->dpriv;
2439 SchroDecoder *sd = dpriv->schrodec;
2440 SchroBuffer *schrobuffer;
2441 SchroFrame *schroframe;
2442 int state;
2443 int frame_width;
2444 int frame_height;
2445
2446 int i;
2447
2448 void *buf;
2449
2450 if (!cont) {
2451 buf = malloc(op->bytes);
2452 memcpy(buf, op->packet, op->bytes);
2453
2454 schrobuffer = schro_buffer_new_with_data(buf, op->bytes);
2455 schrobuffer->priv = buf;
2456
2457 schrobuffer->free = SchroBufferFree;
2458
2459 if (!schro_decoder_push_ready(sd)) fprintf(stderr, "decoder not ready !\n");
2460
2461 schro_decoder_autoparse_push(sd, schrobuffer);
2462 }
2463
2464 while (1) {
2465 state = schro_decoder_autoparse_wait(sd);
2466 switch (state) {
2467
2468 case SCHRO_DECODER_EOS:
2469 printf("EOS\n");
2470 continue;
2471
2472 case SCHRO_DECODER_FIRST_ACCESS_UNIT:
2473 // TODO - re-parse the video format
2474 //printf("fau\n");
2475 continue;
2476
2477 case SCHRO_DECODER_NEED_BITS:
2478 //printf("need bits\n");
2479 return priv->frame_out;
2480
2481 case SCHRO_DECODER_NEED_FRAME:
2482 //printf("need frame\n");
2483 schroframe = schro_frame_new();
2484 schro_frame_set_free_callback(schroframe, SchroFrameFree, NULL);
2485
2486 if (cdata->current_palette == WEED_PALETTE_YUV420P) schroframe->format = SCHRO_FRAME_FORMAT_U8_420;
2487 if (cdata->current_palette == WEED_PALETTE_YUV422P) schroframe->format = SCHRO_FRAME_FORMAT_U8_422;
2488 if (cdata->current_palette == WEED_PALETTE_YUV444P) schroframe->format = SCHRO_FRAME_FORMAT_U8_444;
2489
2490 schroframe->width = frame_width = cdata->frame_width;
2491 schroframe->height = frame_height = cdata->frame_height;
2492
2493 for (i = 0; i < 3; i++) {
2494 schroframe->components[i].width = frame_width;
2495 schroframe->components[i].stride = frame_width;
2496 schroframe->components[i].height = frame_height;
2497 schroframe->components[i].length = frame_width * frame_height;
2498 schroframe->components[i].data = malloc(frame_width * frame_height);
2499
2500 if (i == 0) {
2501 if (cdata->current_palette == WEED_PALETTE_YUV420P) {
2502 frame_width >>= 1;
2503 frame_height >>= 1;
2504 }
2505 if (cdata->current_palette == WEED_PALETTE_YUV422P) {
2506 frame_width >>= 1;
2507 }
2508
2509 } else {
2510 schroframe->components[i].v_shift =
2511 SCHRO_FRAME_FORMAT_V_SHIFT(schroframe->format);
2512 schroframe->components[i].h_shift =
2513 SCHRO_FRAME_FORMAT_H_SHIFT(schroframe->format);
2514 }
2515 }
2516
2517 schro_decoder_add_output_picture(sd, schroframe);
2518 break;
2519
2520 case SCHRO_DECODER_OK:
2521 priv->last_frame = schro_decoder_get_picture_number(sd);
2522 //else priv->last_frame++;
2523 //fprintf(stderr,"dirac decoding picture %ld skip is %d, target %ld\n",priv->last_frame,priv->skip,priv->cframe);
2524 if ((schroframe = schro_decoder_pull(sd)) != NULL) {
2525 if (priv->cframe < 0 || priv->cframe == priv->last_frame) {
2526 priv->frame_out = TRUE;
2527 // copy data to pixel_data
2528 if (pixel_data != NULL) {
2529 schroframe_to_pixel_data(schroframe, pixel_data);
2530 dpriv->schroframe = schroframe;
2531 return TRUE;
2532 }
2533 }
2534 schro_frame_unref(schroframe);
2535 //priv->cframe++;
2536 //priv->skip--;
2537 }
2538 //else printf("Null frame !\n");
2539 if (pixel_data == NULL) return TRUE;
2540 break;
2541
2542 case SCHRO_DECODER_ERROR:
2543 fprintf(stderr, "Schro decoder error !\n");
2544 priv->frame_out = TRUE;
2545 return priv->frame_out;
2546 }
2547 }
2548
2549 return priv->frame_out;
2550 }
2551
2552 #endif
2553
2554
ogg_data_process(lives_clip_data_t * cdata,void * yuvbuffer,boolean cont)2555 static boolean ogg_data_process(lives_clip_data_t *cdata, void *yuvbuffer, boolean cont) {
2556 // yuvbuffer must be cast to whatever decoder expects
2557
2558 int64_t input_pos = 0;
2559 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2560 ogg_t *opriv = priv->opriv;
2561
2562 priv->frame_out = FALSE;
2563
2564 if (!cont) ogg_stream_reset(&priv->vstream->stpriv->os);
2565
2566 #ifdef HAVE_DIRAC
2567 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
2568 priv->ignore_packets = FALSE;
2569 if (!cont) {
2570 dirac_priv_t *dpriv = priv->dpriv;
2571 schro_decoder_reset(dpriv->schrodec);
2572 priv->last_frame = -1;
2573 }
2574 }
2575 #endif
2576
2577 while (!priv->frame_out) {
2578 opriv->page_valid = 0;
2579
2580 if (!cont) {
2581 if (!(input_pos = get_page(cdata, priv->input_position))) {
2582 // should never reach here (except when discovering last frame for dirac)
2583 //fprintf(stderr, "EOF1 while decoding\n");
2584 return FALSE;
2585 }
2586 priv->input_position += input_pos;
2587
2588 if (ogg_page_serialno(&(opriv->current_page)) != priv->vstream->stream_id) continue;
2589 ogg_stream_pagein(&priv->vstream->stpriv->os, &(opriv->current_page));
2590 //printf("pulled page\n");
2591 }
2592
2593 while ((cont && priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) ||
2594 ogg_stream_packetout(&priv->vstream->stpriv->os, &opriv->op) > 0) {
2595
2596 // cframe is the frame we are about to decode
2597
2598 //fprintf(stderr,"cframe is %ld\n",priv->cframe);
2599
2600 #ifdef HAVE_THEORA
2601 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2602
2603 if (!priv->ignore_packets) {
2604 yuv_buffer *yuv = yuvbuffer;
2605 ogg_theora_read(cdata, &opriv->op, yuv);
2606 }
2607
2608 priv->cframe++;
2609 priv->skip--;
2610 }
2611 #endif
2612
2613 #ifdef HAVE_DIRAC
2614 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
2615 uint8_t **yuv = yuvbuffer;
2616
2617 // TODO - if packet is seq start, add to index
2618 //printf("dec packet\n");
2619
2620 ogg_dirac_read(cdata, &opriv->op, yuv, cont);
2621
2622 // dirac can pull several frames from the same packet
2623 if (!priv->frame_out) cont = FALSE;
2624 }
2625 #endif
2626
2627 if (priv->frame_out) break;
2628
2629 sched_yield();
2630 }
2631 priv->ignore_packets = FALSE; // start decoding packets
2632
2633 cont = FALSE;
2634 }
2635
2636 return TRUE;
2637 }
2638
2639
get_frame(const lives_clip_data_t * cdata,int64_t tframe,int * rowstrides,int height,void ** pixel_data)2640 boolean get_frame(const lives_clip_data_t *cdata, int64_t tframe, int *rowstrides, int height, void **pixel_data) {
2641 // seek to frame, and return pixel_data
2642
2643 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2644
2645 #ifdef HAVE_THEORA
2646 yuv_buffer yuv;
2647 register int i;
2648 #endif
2649
2650 #ifdef HAVE_DIRAC
2651 dirac_priv_t *dpriv = priv->dpriv;
2652 ogg_t *opriv = priv->opriv;
2653 #endif
2654
2655 int64_t kframe = -1, xkframe;
2656 boolean cont = FALSE;
2657 int max_frame_diff;
2658 int64_t granulepos = 0;
2659 int64_t ppos_lower = -1, ppos_upper = -1;
2660
2661 static index_entry *fidx = NULL;
2662
2663 #ifdef HAVE_THEORA
2664
2665 register int p;
2666
2667 unsigned char *dst, *src;
2668
2669 int y_black = (cdata->YUV_clamping == WEED_YUV_CLAMPING_CLAMPED) ? 16 : 0;
2670 unsigned char black[4] = {0, 0, 0, 255};
2671
2672 int xheight = (cdata->frame_height >> 1) << 1, pal = cdata->current_palette, nplanes = 1, dstwidth = cdata->width, psize = 1;
2673 int btop = cdata->offs_y, bbot = xheight - 1 - btop;
2674 int bleft = cdata->offs_x, bright = cdata->frame_width - cdata->width - bleft;
2675
2676 if (pixel_data) {
2677 if (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P || pal == WEED_PALETTE_YUV422P || pal == WEED_PALETTE_YUV444P) {
2678 nplanes = 3;
2679 black[0] = y_black;
2680 black[1] = black[2] = 128;
2681 } else if (pal == WEED_PALETTE_YUVA4444P) {
2682 nplanes = 4;
2683 black[0] = y_black;
2684 black[1] = black[2] = 128;
2685 black[3] = 255;
2686 }
2687
2688 if (pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_BGR24) psize = 3;
2689
2690 if (pal == WEED_PALETTE_RGBA32 || pal == WEED_PALETTE_BGRA32 || pal == WEED_PALETTE_ARGB32 || pal == WEED_PALETTE_UYVY8888 ||
2691 pal == WEED_PALETTE_YUYV8888 || pal == WEED_PALETTE_YUV888 || pal == WEED_PALETTE_YUVA8888) psize = 4;
2692
2693 if (pal == WEED_PALETTE_YUV411) psize = 6;
2694
2695 if (pal == WEED_PALETTE_A1) dstwidth >>= 3;
2696
2697 dstwidth *= psize;
2698
2699 if (cdata->frame_height > cdata->height && height == cdata->height) {
2700 // host ignores vertical border
2701 btop = 0;
2702 xheight = (cdata->height >> 1) << 1;
2703 bbot = xheight - 1;
2704 }
2705
2706 if (cdata->frame_width > cdata->width && rowstrides[0] < cdata->frame_width * psize) {
2707 // host ignores horizontal border
2708 bleft = bright = 0;
2709 }
2710 }
2711
2712 #endif
2713
2714 priv->current_pos = priv->input_position;
2715
2716 max_frame_diff = 2 << (priv->vstream->stpriv->keyframe_granule_shift - 2);
2717
2718 tframe += priv->kframe_offset;
2719
2720 if (tframe == priv->last_frame) {
2721 #ifdef HAVE_THEORA
2722 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2723 theora_priv_t *tpriv = priv->tpriv;
2724 theora_decode_YUVout(&tpriv->ts, &yuv);
2725 }
2726 #endif
2727 #ifdef HAVE_DIRAC
2728 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
2729 dirac_priv_t *dpriv = priv->dpriv;
2730 if (dpriv->schroframe) {
2731 schroframe_to_pixel_data(dpriv->schroframe, (uint8_t **)pixel_data);
2732 return TRUE;
2733 }
2734 return FALSE;
2735 }
2736 #endif
2737 } else {
2738 #ifdef HAVE_DIRAC
2739 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC && dpriv->schroframe != NULL) {
2740 schro_frame_unref(dpriv->schroframe);
2741 dpriv->schroframe = NULL;
2742
2743 ppos_lower = priv->vstream->data_start;
2744 ppos_upper = opriv->total_bytes;
2745
2746 max_frame_diff = 16;
2747 }
2748 #endif
2749
2750 if (tframe <= priv->last_frame || tframe - priv->last_frame > max_frame_diff) {
2751
2752 // this is a big kludge, because really for dirac we should always seek from the first frame
2753 // because frames can refer to any earlier frame
2754 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
2755 tframe -= DIRAC_EXTRA_FRAMES ;
2756 }
2757
2758 // need to find a new kframe
2759 pthread_mutex_lock(&priv->idxc->mutex);
2760 fidx = get_bounds_for((lives_clip_data_t *)cdata, tframe, &ppos_lower, &ppos_upper);
2761 if (!fidx) {
2762 //printf("pt a\n");
2763 int64_t last_ret_frame = priv->last_frame;
2764 pthread_mutex_unlock(&priv->idxc->mutex);
2765 granulepos = ogg_seek((lives_clip_data_t *)cdata, tframe, ppos_lower, ppos_upper, TRUE);
2766 pthread_mutex_lock(&priv->idxc->mutex);
2767 priv->last_frame = last_ret_frame;
2768 if (granulepos == -1) return FALSE; // should never happen...
2769 } else granulepos = fidx->value;
2770 pthread_mutex_unlock(&priv->idxc->mutex);
2771 //printf("pt a2\n");
2772
2773 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2774 kframe = granulepos >> priv->vstream->stpriv->keyframe_granule_shift;
2775 //printf("kframe %ld tframe %ld\n",kframe,tframe);
2776 } else {
2777 kframe = granulepos;
2778 // part 2 of the dirac kludge
2779 tframe += DIRAC_EXTRA_FRAMES;
2780 }
2781
2782 if (kframe < priv->kframe_offset) kframe = priv->kframe_offset;
2783 } else kframe = priv->last_kframe;
2784
2785 priv->ignore_packets = FALSE;
2786
2787 //printf("cf %ld and %ld\n",tframe,priv->last_frame);
2788
2789 if (tframe > priv->last_frame && (tframe - priv->last_frame <= max_frame_diff ||
2790 (kframe == priv->last_kframe && priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA))) {
2791 // same keyframe as last time, or next frame; we can continue where we left off
2792 cont = TRUE;
2793 priv->skip = tframe - priv->last_frame - 1;
2794 priv->input_position = priv->current_pos;
2795 //printf("CONTINUING %ld %ld %ld %ld\n",tframe,priv->last_frame,kframe,priv->last_kframe);
2796 } else {
2797 if (!fidx || priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2798 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2799 pthread_mutex_lock(&priv->idxc->mutex);
2800 get_bounds_for((lives_clip_data_t *)cdata, kframe - 1, &ppos_lower, &ppos_upper);
2801 pthread_mutex_unlock(&priv->idxc->mutex);
2802 granulepos = ogg_seek((lives_clip_data_t *)cdata, kframe - 1, ppos_lower, ppos_upper, FALSE);
2803 //fprintf(stderr,"starting from found gpos %ld\n",granulepos);
2804
2805 xkframe = granulepos >> priv->vstream->stpriv->keyframe_granule_shift;
2806
2807 pthread_mutex_lock(&priv->idxc->mutex);
2808 get_bounds_for((lives_clip_data_t *)cdata, xkframe - 1, &ppos_lower, &ppos_upper);
2809 pthread_mutex_unlock(&priv->idxc->mutex);
2810 granulepos = ogg_seek((lives_clip_data_t *)cdata, xkframe - 1, ppos_lower, ppos_upper, FALSE);
2811 //fprintf(stderr,"starting from found gpos %ld\n",granulepos);
2812
2813 xkframe = granulepos >> priv->vstream->stpriv->keyframe_granule_shift;
2814
2815 priv->cframe = xkframe + granulepos - (xkframe <<
2816 priv->vstream->stpriv->keyframe_granule_shift); // cframe will be the next frame we decode
2817 //printf("xkframe is %ld %ld\n",xkframe,priv->cframe);
2818 } else {
2819 priv->cframe = kframe;
2820 priv->input_position = priv->cpagepos;
2821 //printf("SEEK TO %ld\n",priv->cpagepos);
2822 }
2823
2824 if (priv->input_position == priv->vstream->data_start) {
2825 priv->cframe = kframe = priv->kframe_offset;
2826 }
2827
2828 priv->skip = tframe - priv->cframe;
2829 //printf("skip is %ld - %ld = %ld\n",tframe,priv->cframe,priv->skip);
2830 } else {
2831 // same keyframe as last time
2832 priv->input_position = fidx->pagepos;
2833 priv->cframe = kframe = fidx->value;
2834 priv->skip = tframe - priv->cframe + 1;
2835 }
2836
2837 if (priv->input_position > priv->vstream->data_start) {
2838 priv->ignore_packets = TRUE;
2839 }
2840 }
2841
2842 //fprintf(stderr,"getting yuv at %ld\n",input_position);
2843
2844 priv->last_frame = tframe;
2845 priv->last_kframe = kframe;
2846
2847 #ifdef HAVE_THEORA
2848 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2849 if (!ogg_data_process((lives_clip_data_t *)cdata, &yuv, cont)) return FALSE;
2850 }
2851 #endif
2852
2853 #ifdef HAVE_DIRAC
2854 if (priv->vstream->stpriv->fourcc_priv == FOURCC_DIRAC) {
2855 schro_decoder_set_earliest_frame(dpriv->schrodec, tframe);
2856 priv->cframe = tframe;
2857 return ogg_data_process((lives_clip_data_t *)cdata, pixel_data, cont);
2858 }
2859 #endif
2860 }
2861
2862 #ifdef HAVE_THEORA
2863 if (priv->vstream->stpriv->fourcc_priv == FOURCC_THEORA) {
2864 size_t srcadd;
2865
2866 for (p = 0; p < nplanes; p++) {
2867 dst = pixel_data[p];
2868
2869 switch (p) {
2870 case 0:
2871 src = yuv.y;
2872 srcadd = yuv.y_stride;
2873 break;
2874 case 1:
2875 src = yuv.u;
2876 srcadd = yuv.uv_stride;
2877 break;
2878 case 2:
2879 src = yuv.v;
2880 srcadd = yuv.uv_stride;
2881 break;
2882 default:
2883 srcadd = 0;
2884 src = NULL;
2885 break;
2886 }
2887
2888 for (i = 0; i < xheight; i++) {
2889 if (i < btop || i > bbot) {
2890 // top or bottom border, copy black row
2891 if (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P || pal == WEED_PALETTE_YUV422P ||
2892 pal == WEED_PALETTE_YUV444P || pal == WEED_PALETTE_YUVA4444P
2893 || pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_BGR24) {
2894 memset(dst, black[p], dstwidth + (bleft + bright)*psize);
2895 dst += dstwidth + (bleft + bright) * psize;
2896 } else dst += write_black_pixel(dst, pal, dstwidth / psize + bleft + bright, y_black);
2897 continue;
2898 }
2899
2900 if (bleft > 0) {
2901 if (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P
2902 || pal == WEED_PALETTE_YUV422P || pal == WEED_PALETTE_YUV444P ||
2903 pal == WEED_PALETTE_YUVA4444P || pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_BGR24) {
2904 memset(dst, black[p], bleft * psize);
2905 dst += bleft * psize;
2906 } else dst += write_black_pixel(dst, pal, bleft, y_black);
2907 }
2908
2909 memcpy(dst, src, srcadd);
2910 dst += dstwidth;
2911
2912 if (bright > 0) {
2913 if (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P
2914 || pal == WEED_PALETTE_YUV422P || pal == WEED_PALETTE_YUV444P ||
2915 pal == WEED_PALETTE_YUVA4444P || pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_BGR24) {
2916 memset(dst, black[p], bright * psize);
2917 dst += bright * psize;
2918 } else dst += write_black_pixel(dst, pal, bright, y_black);
2919 }
2920
2921 src += srcadd;
2922 }
2923 if (p == 0 && (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P || pal == WEED_PALETTE_YUV422P)) {
2924 dstwidth >>= 1;
2925 bleft >>= 1;
2926 bright >>= 1;
2927 }
2928 if (p == 0 && (pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P)) {
2929 xheight >>= 1;
2930 btop >>= 1;
2931 bbot >>= 1;
2932 }
2933 }
2934 return TRUE;
2935 }
2936 #endif
2937
2938 return FALSE;
2939 }
2940
2941
clip_data_free(lives_clip_data_t * cdata)2942 void clip_data_free(lives_clip_data_t *cdata) {
2943 lives_ogg_priv_t *priv = (lives_ogg_priv_t *)cdata->priv;
2944
2945 // free index entries
2946 if (priv->idxc) idxc_release(cdata);
2947
2948 if (cdata->URI) {
2949 detach_stream(cdata);
2950 }
2951
2952 if (priv->opriv) free(priv->opriv);
2953 lives_struct_free(&cdata->lsd);
2954 }
2955
2956
module_unload(void)2957 void module_unload(void) {
2958 idxc_release_all();
2959 }
2960
2961