3 * @brief Time code sub-picture generator for VLC media player
5 /*****************************************************************************
6 * Copyright © 2013 Rémi Denis-Courmont
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_demux.h>
32 #include <vlc_plugin.h>
34 #define FPS_TEXT N_("Frame rate")
36 static int Open (vlc_object_t
*);
38 static const char *const fps_values
[] = { "24/1", "25/1", "30000/1001", "30/1" };
39 static const char *const fps_texts
[] = { "24", "25", "29.97", "30" };
42 set_shortname (N_("Time code"))
43 set_description (N_("Time code subpicture elementary stream generator"))
44 set_category (CAT_INPUT
)
45 set_subcategory (SUBCAT_INPUT_ACCESS
)
46 set_capability ("access", 0)
47 set_callbacks (Open
, NULL
)
49 add_string ("timecode-fps", "25/1", FPS_TEXT
, FPS_TEXT
, false)
50 change_string_list (fps_values
, fps_texts
)
61 static int DemuxOnce (demux_t
*demux
, bool master
)
63 demux_sys_t
*sys
= demux
->p_sys
;
64 vlc_tick_t pts
= date_Get (&sys
->date
);
68 d
= lldiv (pts
- VLC_TICK_0
, CLOCK_FREQ
);
69 f
= d
.rem
* sys
->date
.i_divider_num
/ sys
->date
.i_divider_den
/ CLOCK_FREQ
;
70 d
= lldiv (d
.quot
, 60);
72 d
= lldiv (d
.quot
, 60);
77 int len
= asprintf (&str
, "%02u:%02u:%02u:%02u", h
, m
, s
, f
);
81 block_t
*block
= block_heap_Alloc (str
, len
+ 1);
82 if (unlikely(block
== NULL
))
85 block
->i_buffer
= len
;
86 assert(str
[len
] == '\0');
88 block
->i_pts
= block
->i_dts
= pts
;
89 block
->i_length
= date_Increment (&sys
->date
, 1) - pts
;
90 es_out_Send (demux
->out
, sys
->es
, block
);
92 es_out_SetPCR(demux
->out
, pts
);
96 static int Demux (demux_t
*demux
)
98 demux_sys_t
*sys
= demux
->p_sys
;
100 if (sys
->next_time
== VLC_TICK_INVALID
) /* Master mode */
101 return DemuxOnce (demux
, true);
104 while (sys
->next_time
> date_Get (&sys
->date
))
106 int val
= DemuxOnce (demux
, false);
113 static int Control (demux_t
*demux
, int query
, va_list args
)
115 demux_sys_t
*sys
= demux
->p_sys
;
119 case DEMUX_GET_POSITION
:
120 *va_arg (args
, float *) = 0.f
;
123 case DEMUX_GET_LENGTH
:
124 *va_arg (args
, int64_t *) = INT64_C(0);
128 *va_arg (args
, int64_t *) = date_Get (&sys
->date
);
132 date_Set (&sys
->date
, va_arg (args
, int64_t));
135 case DEMUX_SET_NEXT_DEMUX_TIME
:
137 const vlc_tick_t pts
= va_arg (args
, vlc_tick_t
);
139 if (sys
->next_time
== VLC_TICK_INVALID
) /* first invocation? */
141 date_Set (&sys
->date
, pts
);
142 date_Decrement (&sys
->date
, 1);
144 sys
->next_time
= pts
;
148 case DEMUX_GET_PTS_DELAY
:
150 int64_t *v
= va_arg (args
, int64_t *);
151 *v
= INT64_C(1000) * var_InheritInteger (demux
, "live-caching");
155 case DEMUX_CAN_PAUSE
:
156 case DEMUX_CAN_CONTROL_PACE
:
158 *va_arg (args
, bool *) = true;
167 static int Open (vlc_object_t
*obj
)
169 demux_t
*demux
= (demux_t
*)obj
;
170 if (demux
->out
== NULL
)
173 demux_sys_t
*sys
= vlc_obj_malloc(obj
, sizeof (*sys
));
174 if (unlikely(sys
== NULL
))
178 es_format_Init (&fmt
, SPU_ES
, VLC_CODEC_ITU_T140
);
179 sys
->es
= es_out_Add (demux
->out
, &fmt
);
182 if (var_InheritURational (demux
, &num
, &den
, "timecode-fps")
185 msg_Err (demux
, "invalid frame rate");
189 date_Init (&sys
->date
, num
, den
);
190 date_Set (&sys
->date
, VLC_TICK_0
);
191 sys
->next_time
= VLC_TICK_INVALID
;
194 demux
->pf_demux
= Demux
;
195 demux
->pf_control
= Control
;