MythTV  0.26-pre
graphics_processor.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of libbluray
00003  * Copyright (C) 2010  hpi1
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library. If not, see
00017  * <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include "graphics_processor.h"
00021 
00022 #include "ig_decode.h"
00023 #include "pg_decode.h"
00024 #include "pes_buffer.h"
00025 #include "m2ts_demux.h"
00026 
00027 #include "util/macro.h"
00028 #include "util/logging.h"
00029 #include "util/bits.h"
00030 
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <inttypes.h>
00034 
00035 #define GP_TRACE(...) do {} while (0)
00036 
00037 
00038 /*
00039  * segment types
00040  */
00041 
00042 typedef enum {
00043     PGS_PALETTE        = 0x14,
00044     PGS_OBJECT         = 0x15,
00045     PGS_PG_COMPOSITION = 0x16,
00046     PGS_WINDOW         = 0x17,
00047     PGS_IG_COMPOSITION = 0x18,
00048     PGS_END_OF_DISPLAY = 0x80,
00049 } pgs_segment_type_e;
00050 
00051 /*
00052  * PG_DISPLAY_SET
00053  */
00054 
00055 void pg_display_set_free(PG_DISPLAY_SET **s)
00056 {
00057     if (s && *s) {
00058         unsigned ii;
00059         for (ii = 0; ii < (*s)->num_object; ii++) {
00060             pg_clean_object(&(*s)->object[ii]);
00061         }
00062         ig_free_interactive(&(*s)->ics);
00063 
00064         X_FREE((*s)->window);
00065         X_FREE((*s)->object);
00066         X_FREE((*s)->palette);
00067 
00068         X_FREE(*s);
00069     }
00070 }
00071 
00072 /*
00073  * segment handling
00074  */
00075 
00076 static PES_BUFFER *_find_segment_by_idv(PES_BUFFER *p,
00077                                         uint8_t seg_type, unsigned idv_pos,
00078                                         uint8_t *idv, unsigned idv_len)
00079 {
00080     while (p && (p->buf[0] != seg_type || memcmp(p->buf + idv_pos, idv, idv_len))) {
00081         p = p->next;
00082     }
00083     return p;
00084 }
00085 
00086 static void _join_fragments(PES_BUFFER *p1, PES_BUFFER *p2, int data_pos)
00087 {
00088     unsigned new_len = p1->len + p2->len - data_pos;
00089 
00090     if (p1->size < new_len) {
00091         p1->size = new_len + 1;
00092         p1->buf  = realloc(p1->buf, p1->size);
00093     }
00094 
00095     memcpy(p1->buf + p1->len, p2->buf + data_pos, p2->len - data_pos);
00096     p1->len = new_len;
00097     p2->len = 0;
00098 }
00099 
00100 /* return 1 if segment is ready for decoding, 0 if more data is needed */
00101 static int _join_segment_fragments(struct pes_buffer_s *p)
00102 {
00103     uint8_t type = p->buf[0];
00104     unsigned id_pos = 0, id_len = 3, sd_pos = 6, data_pos = 0;
00105 
00106     if (p->len < 3) {
00107         return 1;
00108     }
00109 
00110     /* check segment type */
00111 
00112     if (type == PGS_OBJECT) {
00113         id_pos = 3;
00114         sd_pos = 6;
00115         data_pos = 7;
00116     }
00117     else if (type == PGS_IG_COMPOSITION) {
00118         id_pos = 8;
00119         sd_pos = 11;
00120         data_pos = 12;
00121     }
00122     else {
00123         return 1;
00124     }
00125 
00126     /* check sequence descriptor - is segment complete ? */
00127 
00128     BD_PG_SEQUENCE_DESCRIPTOR sd;
00129     BITBUFFER bb;
00130     bb_init(&bb, p->buf + sd_pos, 3);
00131     pg_decode_sequence_descriptor(&bb, &sd);
00132 
00133     if (sd.last_in_seq) {
00134         return 1;
00135     }
00136     if (!sd.first_in_seq) {
00137         return 1;
00138     }
00139 
00140     /* find next fragment(s) */
00141 
00142     PES_BUFFER *next;
00143     while (NULL != (next = _find_segment_by_idv(p->next, p->buf[0], id_pos, p->buf + id_pos, id_len))) {
00144 
00145         bb_init(&bb, next->buf + sd_pos, 3);
00146         pg_decode_sequence_descriptor(&bb, &sd);
00147 
00148         _join_fragments(p, next, data_pos);
00149 
00150         pes_buffer_remove(&p, next);
00151 
00152         if (sd.last_in_seq) {
00153             /* set first + last in sequence descriptor */
00154             p->buf[sd_pos] = 0xff;
00155             return 1;
00156         }
00157     }
00158 
00159     /* do not delay decoding if there are other segments queued (missing fragment ?) */
00160     return !!p->next;
00161 }
00162 
00163 /*
00164  * segment decoding
00165  */
00166 
00167 static int _decode_wds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00168 {
00169     (void)s;
00170     (void)bb;
00171     (void)p;
00172 
00173     BD_DEBUG(DBG_DECODE | DBG_CRIT, "unhandled segment type (PGS_WINDOW)\n");
00174     return 0;
00175 }
00176 
00177 static int _decode_ods(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00178 {
00179     /* search for object to be updated */
00180 
00181     if (s->object) {
00182         BITBUFFER bb_tmp = *bb;
00183         uint16_t   id     = bb_read(&bb_tmp, 16);
00184         unsigned  ii;
00185 
00186         for (ii = 0; ii < s->num_object; ii++) {
00187             if (s->object[ii].id == id) {
00188                 if (pg_decode_object(bb, &s->object[ii])) {
00189                     s->object[ii].pts = p->pts;
00190                     return 1;
00191                 }
00192                 return 0;
00193             }
00194         }
00195     }
00196 
00197     /* add and decode new object */
00198 
00199     s->object = realloc(s->object, sizeof(s->object[0]) * (s->num_object + 1));
00200     memset(&s->object[s->num_object], 0, sizeof(s->object[0]));
00201 
00202     if (pg_decode_object(bb, &s->object[s->num_object])) {
00203         s->object[s->num_object].pts = p->pts;
00204         s->num_object++;
00205         return 1;
00206     }
00207 
00208     return 0;
00209 }
00210 
00211 static int _decode_pds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00212 {
00213     /* search for palette to be updated */
00214 
00215     if (s->palette) {
00216         BITBUFFER bb_tmp = *bb;
00217         uint8_t   id     = bb_read(&bb_tmp, 8);
00218         unsigned  ii;
00219 
00220         for (ii = 0; ii < s->num_palette; ii++) {
00221             if (s->palette[ii].id == id) {
00222                 int rr;
00223                 if ( (s->ics && s->ics->composition_descriptor.state == 0) ||
00224                      (s->pcs && s->pcs->composition_descriptor.state == 0)) {
00225                     /* 8.8.3.1.1 */
00226                     rr = pg_decode_palette_update(bb, &s->palette[ii]);
00227                 } else {
00228                     rr = pg_decode_palette(bb, &s->palette[ii]);
00229                 }
00230                 if (rr) {
00231                     s->palette[ii].pts = p->pts;
00232                     return 1;
00233                 }
00234                 return 0;
00235             }
00236         }
00237     }
00238 
00239     /* add and decode new palette */
00240 
00241     s->palette = realloc(s->palette, sizeof(s->palette[0]) * (s->num_palette + 1));
00242     memset(&s->palette[s->num_palette], 0, sizeof(s->palette[0]));
00243 
00244     if (pg_decode_palette(bb, &s->palette[s->num_palette])) {
00245         s->palette[s->num_palette].pts = p->pts;
00246         s->num_palette++;
00247         return 1;
00248     }
00249 
00250     return 0;
00251 }
00252 
00253 static void _check_epoch_start(PG_DISPLAY_SET *s)
00254 {
00255     if ((s->pcs && s->pcs->composition_descriptor.state == 2) ||
00256         (s->ics && s->ics->composition_descriptor.state == 2)) {
00257         /* epoch start, drop all cached data */
00258 
00259         unsigned ii;
00260         for (ii = 0; ii < s->num_object; ii++) {
00261             pg_clean_object(&s->object[ii]);
00262         }
00263 
00264         s->num_palette = 0;
00265         s->num_window  = 0;
00266         s->num_object  = 0;
00267 
00268         s->epoch_start = 1;
00269 
00270     } else {
00271         s->epoch_start = 0;
00272     }
00273 }
00274 
00275 static int _decode_pcs(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00276 {
00277     pg_free_composition(&s->pcs);
00278     s->pcs = calloc(1, sizeof(*s->pcs));
00279 
00280     if (!pg_decode_composition(bb, s->pcs)) {
00281         pg_free_composition(&s->pcs);
00282         return 0;
00283     }
00284 
00285     s->pcs->pts  = p->pts;
00286     s->valid_pts = p->pts;
00287 
00288     _check_epoch_start(s);
00289 
00290     return 1;
00291 }
00292 
00293 static int _decode_ics(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
00294 {
00295     ig_free_interactive(&s->ics);
00296     s->ics = calloc(1, sizeof(*s->ics));
00297 
00298     if (!ig_decode_interactive(bb, s->ics)) {
00299         ig_free_interactive(&s->ics);
00300         return 0;
00301     }
00302 
00303     s->ics->pts  = p->pts;
00304     s->valid_pts = p->pts;
00305 
00306     _check_epoch_start(s);
00307 
00308     return 1;
00309 }
00310 
00311 static int _decode_segment(PG_DISPLAY_SET *s, PES_BUFFER *p)
00312 {
00313     BITBUFFER bb;
00314     bb_init(&bb, p->buf, p->len);
00315 
00316     uint8_t type   =    bb_read(&bb, 8);
00317     /*uint16_t len = */ bb_read(&bb, 16);
00318 
00319     switch (type) {
00320         case PGS_OBJECT:
00321             return _decode_ods(s, &bb, p);
00322 
00323         case PGS_PALETTE:
00324             return _decode_pds(s, &bb, p);
00325 
00326         case PGS_WINDOW:
00327             return _decode_wds(s, &bb, p);
00328 
00329         case PGS_PG_COMPOSITION:
00330             return _decode_pcs(s, &bb, p);
00331 
00332         case PGS_IG_COMPOSITION:
00333             return _decode_ics(s, &bb, p);
00334 
00335         case PGS_END_OF_DISPLAY:
00336             s->complete = 1;
00337             return 1;
00338 
00339         default:
00340             BD_DEBUG(DBG_DECODE | DBG_CRIT, "unknown segment type 0x%x\n", type);
00341             break;
00342     }
00343 
00344     return 0;
00345 }
00346 
00347 /*
00348  * mpeg-pes interface
00349  */
00350 
00351 int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t stc)
00352 {
00353     if (!s) {
00354         return 0;
00355     }
00356 
00357     if (*s == NULL) {
00358         *s = calloc(1, sizeof(PG_DISPLAY_SET));
00359     }
00360 
00361     while (*p) {
00362 
00363         /* time to decode next segment ? */
00364         if (stc >= 0 && (*p)->dts > stc) {
00365             GP_TRACE("Segment dts > stc (%"PRId64" > %"PRId64" ; diff %"PRId64")\n",
00366                      (*p)->dts, stc, (*p)->dts - stc);
00367             return 0;
00368         }
00369 
00370         /* all fragments present ? */
00371         if (!_join_segment_fragments(*p)) {
00372             GP_TRACE("splitted segment not complete, waiting for next fragment\n");
00373             return 0;
00374         }
00375 
00376         if ((*p)->len <= 2) {
00377             BD_DEBUG(DBG_DECODE, "segment too short, skipping (%d bytes)\n", (*p)->len);
00378             pes_buffer_remove(p, *p);
00379             continue;
00380         }
00381 
00382         /* decode segment */
00383 
00384         GP_TRACE("Decoding segment, dts %010"PRId64" pts %010"PRId64" len %d\n",
00385                  (*p)->dts, (*p)->pts, (*p)->len);
00386 
00387         (*s)->complete = 0;
00388 
00389         _decode_segment(*s, *p);
00390 
00391         pes_buffer_remove(p, *p);
00392 
00393         if ((*s)->complete) {
00394             return 1;
00395         }
00396 
00397     }
00398 
00399     return 0;
00400 }
00401 
00402 /*
00403  * mpeg-ts interface
00404  */
00405 
00406 struct graphics_processor_s {
00407     uint16_t    pid;
00408     M2TS_DEMUX  *demux;
00409     PES_BUFFER  *queue;
00410 };
00411 
00412 GRAPHICS_PROCESSOR *graphics_processor_init(void)
00413 {
00414     GRAPHICS_PROCESSOR *p = calloc(1, sizeof(*p));
00415 
00416     return p;
00417 }
00418 
00419 void graphics_processor_free(GRAPHICS_PROCESSOR **p)
00420 {
00421     if (p && *p) {
00422         m2ts_demux_free(&(*p)->demux);
00423         pes_buffer_free(&(*p)->queue);
00424 
00425         X_FREE(*p);
00426     }
00427 }
00428 
00429 int graphics_processor_decode_ts(GRAPHICS_PROCESSOR *p,
00430                                  PG_DISPLAY_SET **s,
00431                                  uint16_t pid, uint8_t *unit, unsigned num_units,
00432                                  int64_t stc)
00433 {
00434     unsigned ii;
00435 
00436     if (pid != p->pid) {
00437         m2ts_demux_free(&p->demux);
00438         pes_buffer_free(&p->queue);
00439     }
00440     if (!p->demux) {
00441         p->demux = m2ts_demux_init(pid);
00442         p->pid   = pid;
00443     }
00444 
00445     for (ii = 0; ii < num_units; ii++) {
00446         pes_buffer_append(&p->queue, m2ts_demux(p->demux, unit));
00447         unit += 6144;
00448     }
00449 
00450     if (p->queue) {
00451         return graphics_processor_decode_pes(s, &p->queue, stc);
00452     }
00453 
00454     return 0;
00455 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends