~ubuntu-branches/ubuntu/precise/gst-plugins-bad0.10/precise-proposed

« back to all changes in this revision

Viewing changes to ext/resindvd/resindvdsrc.c

Tags: upstream-0.10.17.2
Import upstream version 0.10.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* GStreamer
2
 
 * Copyright (C) 2008 Jan Schmidt <thaytan@noraisin.net>
 
2
 * Copyright (C) 2008-2009 Jan Schmidt <thaytan@noraisin.net>
3
3
 *
4
4
 * This library is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU Library General Public
27
27
#include <gst/gst.h>
28
28
#include <gst/gst-i18n-plugin.h>
29
29
#include <gst/interfaces/navigation.h>
 
30
#include <gst/video/video.h>
30
31
 
31
32
#include "resindvdsrc.h"
32
33
 
97
98
 
98
99
static void rsn_dvdsrc_register_extra (GType rsn_dvdsrc_type);
99
100
 
100
 
GST_BOILERPLATE_FULL (resinDvdSrc, rsn_dvdsrc, RsnBaseSrc,
101
 
    RSN_TYPE_BASE_SRC, rsn_dvdsrc_register_extra);
 
101
GST_BOILERPLATE_FULL (resinDvdSrc, rsn_dvdsrc, GstBaseSrc,
 
102
    GST_TYPE_BASE_SRC, rsn_dvdsrc_register_extra);
102
103
 
103
104
static gboolean read_vts_info (resinDvdSrc * src);
104
105
 
109
110
 
110
111
static void rsn_dvdsrc_finalize (GObject * object);
111
112
 
112
 
static gboolean rsn_dvdsrc_start (RsnBaseSrc * bsrc);
113
 
static gboolean rsn_dvdsrc_stop (RsnBaseSrc * bsrc);
114
 
static gboolean rsn_dvdsrc_unlock (RsnBaseSrc * bsrc);
115
 
static gboolean rsn_dvdsrc_unlock_stop (RsnBaseSrc * bsrc);
 
113
static gboolean rsn_dvdsrc_start (GstBaseSrc * bsrc);
 
114
static gboolean rsn_dvdsrc_stop (GstBaseSrc * bsrc);
 
115
static gboolean rsn_dvdsrc_unlock (GstBaseSrc * bsrc);
 
116
static gboolean rsn_dvdsrc_unlock_stop (GstBaseSrc * bsrc);
116
117
 
117
 
static gboolean rsn_dvdsrc_is_seekable (RsnBaseSrc * bsrc);
118
 
static gboolean rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
 
118
static gboolean rsn_dvdsrc_is_seekable (GstBaseSrc * bsrc);
 
119
static gboolean rsn_dvdsrc_prepare_seek (GstBaseSrc * bsrc, GstEvent * event,
119
120
    GstSegment * segment);
120
 
static gboolean rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment);
 
121
static gboolean rsn_dvdsrc_do_seek (GstBaseSrc * bsrc, GstSegment * segment);
121
122
static GstStateChangeReturn
122
123
rsn_dvdsrc_change_state (GstElement * element, GstStateChange transition);
123
124
 
139
140
static void rsn_dvdsrc_schedule_nav_cb (resinDvdSrc * src,
140
141
    RsnDvdPendingNav * next_nav);
141
142
 
142
 
static gboolean rsn_dvdsrc_check_get_range (RsnBaseSrc * src);
143
 
static GstFlowReturn rsn_dvdsrc_create (RsnBaseSrc * bsrc, guint64 offset,
 
143
static gboolean rsn_dvdsrc_check_get_range (GstBaseSrc * src);
 
144
static GstFlowReturn rsn_dvdsrc_create (GstBaseSrc * bsrc, guint64 offset,
144
145
    guint length, GstBuffer ** buf);
145
 
static gboolean rsn_dvdsrc_src_event (RsnBaseSrc * basesrc, GstEvent * event);
146
 
static gboolean rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query);
 
146
static gboolean rsn_dvdsrc_src_event (GstBaseSrc * basesrc, GstEvent * event);
 
147
static gboolean rsn_dvdsrc_src_query (GstBaseSrc * basesrc, GstQuery * query);
147
148
 
148
149
static GstClockTime ifotime_to_gsttime (dvd_time_t * ifo_time);
149
150
static void rsn_dvdsrc_send_commands_changed (resinDvdSrc * src);
206
207
{
207
208
  GObjectClass *gobject_class;
208
209
  GstElementClass *gstelement_class;
209
 
  RsnBaseSrcClass *gstbasesrc_class;
 
210
  GstBaseSrcClass *gstbasesrc_class;
210
211
 
211
212
  gobject_class = (GObjectClass *) klass;
212
213
  gstelement_class = (GstElementClass *) klass;
213
 
  gstbasesrc_class = RSN_BASE_SRC_CLASS (klass);
 
214
  gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
214
215
 
215
216
  gobject_class->finalize = rsn_dvdsrc_finalize;
216
217
  gobject_class->set_property = rsn_dvdsrc_set_property;
260
261
  rsndvdsrc->branching = FALSE;
261
262
  rsndvdsrc->still_cond = g_cond_new ();
262
263
 
263
 
  gst_base_src_set_format (RSN_BASE_SRC (rsndvdsrc), GST_FORMAT_TIME);
 
264
  gst_base_src_set_format (GST_BASE_SRC (rsndvdsrc), GST_FORMAT_TIME);
264
265
}
265
266
 
266
267
static void
279
280
}
280
281
 
281
282
static gboolean
282
 
rsn_dvdsrc_unlock (RsnBaseSrc * bsrc)
 
283
rsn_dvdsrc_unlock (GstBaseSrc * bsrc)
283
284
{
284
285
  resinDvdSrc *src = RESINDVDSRC (bsrc);
285
286
 
292
293
}
293
294
 
294
295
static gboolean
295
 
rsn_dvdsrc_unlock_stop (RsnBaseSrc * bsrc)
 
296
rsn_dvdsrc_unlock_stop (GstBaseSrc * bsrc)
296
297
{
297
298
  resinDvdSrc *src = RESINDVDSRC (bsrc);
298
299
 
354
355
}
355
356
 
356
357
static gboolean
357
 
rsn_dvdsrc_start (RsnBaseSrc * bsrc)
 
358
rsn_dvdsrc_start (GstBaseSrc * bsrc)
358
359
{
359
360
  resinDvdSrc *src = RESINDVDSRC (bsrc);
360
361
 
511
512
}
512
513
 
513
514
static gboolean
514
 
rsn_dvdsrc_stop (RsnBaseSrc * bsrc)
 
515
rsn_dvdsrc_stop (GstBaseSrc * bsrc)
515
516
{
516
517
  resinDvdSrc *src = RESINDVDSRC (bsrc);
517
518
  gboolean ret = TRUE;
597
598
  GstEvent *still_event;
598
599
  GstEvent *hl_event;
599
600
  gboolean cmds_changed;
600
 
  GstStructure *s;
601
601
  GstEvent *seg_event;
602
 
  GstSegment *segment = &(RSN_BASE_SRC (src)->segment);
 
602
  GstSegment *segment = &(GST_BASE_SRC (src)->segment);
603
603
 
604
604
  if (src->in_still_state == FALSE) {
605
605
    GST_DEBUG_OBJECT (src, "**** Start STILL FRAME. Duration %d ****",
610
610
    else
611
611
      src->still_time_remaining = GST_SECOND * duration;
612
612
 
613
 
    /* Send a close-segment event, and a dvd-still start
 
613
    /* Send a close-segment event, and a still-frame start
614
614
     * event, then sleep */
615
 
    s = gst_structure_new ("application/x-gst-dvd",
616
 
        "event", G_TYPE_STRING, "dvd-still",
617
 
        "still-state", G_TYPE_BOOLEAN, TRUE, NULL);
618
 
    still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
 
615
    still_event = gst_video_event_new_still_frame (TRUE);
619
616
 
620
617
    gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts);
621
618
 
632
629
    /* Now, send the events. We need to drop the dvd lock while doing so,
633
630
     * and then check after if we got flushed */
634
631
    g_mutex_unlock (src->dvd_lock);
635
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), still_event);
636
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), seg_event);
 
632
    gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event);
 
633
    gst_pad_push_event (GST_BASE_SRC_PAD (src), seg_event);
637
634
    if (hl_event) {
638
635
      GST_LOG_OBJECT (src, "Sending highlight event before still");
639
 
      gst_pad_push_event (RSN_BASE_SRC_PAD (src), hl_event);
 
636
      gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
640
637
    }
641
638
    if (cmds_changed)
642
639
      rsn_dvdsrc_send_commands_changed (src);
734
731
 
735
732
    /* Tell downstream the still is over.
736
733
     * We only do this if the still isn't interrupted: */
737
 
    s = gst_structure_new ("application/x-gst-dvd",
738
 
        "event", G_TYPE_STRING, "dvd-still",
739
 
        "still-state", G_TYPE_BOOLEAN, FALSE, NULL);
740
 
    still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
 
734
    still_event = gst_video_event_new_still_frame (FALSE);
741
735
 
742
736
    /* If the segment was too short in a timed still, it may need extending */
743
737
    if (segment->last_stop < segment->start + GST_SECOND * duration)
745
739
          segment->start + (GST_SECOND * duration));
746
740
 
747
741
    g_mutex_unlock (src->dvd_lock);
748
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), still_event);
 
742
    gst_pad_push_event (GST_BASE_SRC_PAD (src), still_event);
749
743
    g_mutex_lock (src->dvd_lock);
750
744
  }
751
745
 
1095
1089
    g_mutex_unlock (src->dvd_lock);
1096
1090
    GST_DEBUG_OBJECT (src, "Sending highlight event - button %d",
1097
1091
        src->active_button);
1098
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), hl_event);
 
1092
    gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
1099
1093
    g_mutex_lock (src->dvd_lock);
1100
1094
  }
1101
1095
 
1229
1223
}
1230
1224
 
1231
1225
static gboolean
1232
 
rsn_dvdsrc_check_get_range (RsnBaseSrc * src)
 
1226
rsn_dvdsrc_check_get_range (GstBaseSrc * src)
1233
1227
{
1234
1228
  /* ResinDVD never operates in pull mode. There might be
1235
1229
   * a reason to in the future though? */
1237
1231
}
1238
1232
 
1239
1233
static GstFlowReturn
1240
 
rsn_dvdsrc_create (RsnBaseSrc * bsrc, guint64 offset,
 
1234
rsn_dvdsrc_create (GstBaseSrc * bsrc, guint64 offset,
1241
1235
    guint length, GstBuffer ** outbuf)
1242
1236
{
1243
1237
  resinDvdSrc *src = RESINDVDSRC (bsrc);
1244
 
  GstSegment *segment = &(RSN_BASE_SRC (src)->segment);
 
1238
  GstSegment *segment = &(GST_BASE_SRC (src)->segment);
1245
1239
  GstFlowReturn ret;
1246
1240
  GstEvent *streams_event = NULL;
1247
1241
  GstEvent *clut_event = NULL;
1292
1286
   * we change segment */
1293
1287
  if (streams_event) {
1294
1288
    GST_LOG_OBJECT (src, "Pushing stream layout event");
1295
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), streams_event);
 
1289
    gst_pad_push_event (GST_BASE_SRC_PAD (src), streams_event);
1296
1290
  }
1297
1291
  if (clut_event) {
1298
1292
    GST_LOG_OBJECT (src, "Pushing clut event");
1299
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), clut_event);
 
1293
    gst_pad_push_event (GST_BASE_SRC_PAD (src), clut_event);
1300
1294
  }
1301
1295
  /* Out of band events */
1302
1296
  if (spu_select_event) {
1303
1297
    GST_LOG_OBJECT (src, "Pushing spu_select event");
1304
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), spu_select_event);
 
1298
    gst_pad_push_event (GST_BASE_SRC_PAD (src), spu_select_event);
1305
1299
  }
1306
1300
  if (audio_select_event) {
1307
1301
    GST_LOG_OBJECT (src, "Pushing audio_select event");
1308
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), audio_select_event);
 
1302
    gst_pad_push_event (GST_BASE_SRC_PAD (src), audio_select_event);
1309
1303
  }
1310
1304
 
1311
1305
  if (src->need_segment) {
1323
1317
        GST_TIME_ARGS (src->cur_start_ts), GST_TIME_ARGS (src->cur_end_ts),
1324
1318
        GST_TIME_ARGS (src->cur_vobu_base_ts), GST_TIME_ARGS (position));
1325
1319
 
1326
 
    gst_base_src_new_seamless_segment (RSN_BASE_SRC (src),
 
1320
    gst_base_src_new_seamless_segment (GST_BASE_SRC (src),
1327
1321
        src->cur_start_ts, -1, position);
1328
1322
 
1329
1323
    src->need_segment = FALSE;
1363
1357
  if (highlight_event) {
1364
1358
    GST_LOG_OBJECT (src, "Pushing highlight event with TS %" GST_TIME_FORMAT,
1365
1359
        GST_TIME_ARGS (GST_EVENT_TIMESTAMP (highlight_event)));
1366
 
    gst_pad_push_event (RSN_BASE_SRC_PAD (src), highlight_event);
 
1360
    gst_pad_push_event (GST_BASE_SRC_PAD (src), highlight_event);
1367
1361
  }
1368
1362
 
1369
1363
  if (angles_msg) {
1712
1706
      if (hl_event) {
1713
1707
        GST_DEBUG_OBJECT (src, "Sending highlight change event - button: %d",
1714
1708
            src->active_button);
1715
 
        gst_pad_push_event (RSN_BASE_SRC_PAD (src), hl_event);
 
1709
        gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
1716
1710
      }
1717
1711
 
1718
1712
      /* Send ourselves a seek event to wake everything up and flush */
1750
1744
    if (hl_event) {
1751
1745
      GST_DEBUG_OBJECT (src, "Sending highlight change event - button: %d",
1752
1746
          src->active_button);
1753
 
      gst_pad_push_event (RSN_BASE_SRC_PAD (src), hl_event);
 
1747
      gst_pad_push_event (GST_BASE_SRC_PAD (src), hl_event);
1754
1748
    }
1755
1749
 
1756
1750
    if (cmds_changed)
2153
2147
    GstClockTime ts)
2154
2148
{
2155
2149
  RsnDvdPendingNav *pend_nav = g_new0 (RsnDvdPendingNav, 1);
2156
 
  GstSegment *seg = &(RSN_BASE_SRC (src)->segment);
 
2150
  GstSegment *seg = &(GST_BASE_SRC (src)->segment);
2157
2151
 
2158
2152
  pend_nav->buffer = gst_buffer_ref (nav_buf);
2159
2153
  pend_nav->ts = ts;
2327
2321
}
2328
2322
 
2329
2323
static gboolean
2330
 
rsn_dvdsrc_src_event (RsnBaseSrc * basesrc, GstEvent * event)
 
2324
rsn_dvdsrc_src_event (GstBaseSrc * basesrc, GstEvent * event)
2331
2325
{
2332
2326
  resinDvdSrc *src = RESINDVDSRC (basesrc);
2333
2327
  gboolean res;
2346
2340
      GST_DEBUG_OBJECT (src, "%s seek event",
2347
2341
          src->flushing_seek ? "flushing" : "non-flushing");
2348
2342
 
2349
 
      res = RSN_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
 
2343
      res = GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
2350
2344
      break;
2351
2345
    }
2352
2346
    default:
2353
2347
      GST_LOG_OBJECT (src, "handling %s event", GST_EVENT_TYPE_NAME (event));
2354
2348
 
2355
 
      res = RSN_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
 
2349
      res = GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event);
2356
2350
      break;
2357
2351
  }
2358
2352
 
2403
2397
}
2404
2398
 
2405
2399
static gboolean
2406
 
rsn_dvdsrc_src_query (RsnBaseSrc * basesrc, GstQuery * query)
 
2400
rsn_dvdsrc_src_query (GstBaseSrc * basesrc, GstQuery * query)
2407
2401
{
2408
2402
  resinDvdSrc *src = RESINDVDSRC (basesrc);
2409
2403
  gboolean res = FALSE;
2484
2478
      if (nq_type != GST_NAVIGATION_QUERY_INVALID)
2485
2479
        res = rsn_dvdsrc_handle_navigation_query (src, nq_type, query);
2486
2480
      else
2487
 
        res = RSN_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
 
2481
        res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
2488
2482
      break;
2489
2483
    }
2490
2484
    default:
2491
 
      res = RSN_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
 
2485
      res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query);
2492
2486
      break;
2493
2487
  }
2494
2488
 
2496
2490
}
2497
2491
 
2498
2492
static gboolean
2499
 
rsn_dvdsrc_is_seekable (RsnBaseSrc * bsrc)
 
2493
rsn_dvdsrc_is_seekable (GstBaseSrc * bsrc)
2500
2494
{
2501
2495
  return TRUE;
2502
2496
}
2503
2497
 
2504
2498
static gboolean
2505
 
rsn_dvdsrc_prepare_seek (RsnBaseSrc * bsrc, GstEvent * event,
 
2499
rsn_dvdsrc_prepare_seek (GstBaseSrc * bsrc, GstEvent * event,
2506
2500
    GstSegment * segment)
2507
2501
{
2508
2502
  GstSeekType cur_type, stop_type;
2532
2526
  }
2533
2527
 
2534
2528
  /* Let basesrc handle other formats */
2535
 
  ret = RSN_BASE_SRC_CLASS (parent_class)->prepare_seek_segment (bsrc,
 
2529
  ret = GST_BASE_SRC_CLASS (parent_class)->prepare_seek_segment (bsrc,
2536
2530
      event, segment);
2537
2531
 
2538
2532
  return ret;
2591
2585
 
2592
2586
  /* Get the time map */
2593
2587
  title_tmap = vts_tmapt->tmap + vts_ttn - 1;
 
2588
  if (title_tmap->tmu == 0)
 
2589
    return -1;
 
2590
 
2594
2591
  entry = ts / (title_tmap->tmu * GST_SECOND);
2595
2592
  if (entry == 0)
2596
2593
    return 0;
2658
2655
}
2659
2656
 
2660
2657
static gboolean
2661
 
rsn_dvdsrc_do_seek (RsnBaseSrc * bsrc, GstSegment * segment)
 
2658
rsn_dvdsrc_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
2662
2659
{
2663
2660
  resinDvdSrc *src = RESINDVDSRC (bsrc);
2664
2661
  gboolean ret = FALSE;