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
*);
37 static void Close (vlc_object_t
*);
39 static const char *const fps_values
[] = { "24/1", "25/1", "30000/1001", "30/1" };
40 static const char *const fps_texts
[] = { "24", "25", "29.97", "30" };
43 set_shortname (N_("Time code"))
44 set_description (N_("Time code subpicture elementary stream generator"))
45 set_category (CAT_INPUT
)
46 set_subcategory (SUBCAT_INPUT_ACCESS
)
47 set_capability ("access_demux", 0)
48 set_callbacks (Open
, Close
)
50 add_string ("timecode-fps", "25/1", FPS_TEXT
, FPS_TEXT
, false)
51 change_string_list (fps_values
, fps_texts
)
62 static int DemuxOnce (demux_t
*demux
, bool master
)
64 demux_sys_t
*sys
= demux
->p_sys
;
65 mtime_t pts
= date_Get (&sys
->date
);
69 d
= lldiv (pts
, CLOCK_FREQ
);
70 f
= d
.rem
* sys
->date
.i_divider_num
/ sys
->date
.i_divider_den
/ CLOCK_FREQ
;
71 d
= lldiv (d
.quot
, 60);
73 d
= lldiv (d
.quot
, 60);
78 int len
= asprintf (&str
, "%02u:%02u:%02u:%02u", h
, m
, s
, f
);
82 block_t
*block
= block_heap_Alloc (str
, len
+ 1);
83 if (unlikely(block
== NULL
))
86 block
->i_buffer
= len
;
87 assert(str
[len
] == '\0');
89 block
->i_pts
= block
->i_dts
= pts
;
90 block
->i_length
= date_Increment (&sys
->date
, 1) - pts
;
91 es_out_Send (demux
->out
, sys
->es
, block
);
93 es_out_Control (demux
->out
, ES_OUT_SET_PCR
, pts
);
97 static int Demux (demux_t
*demux
)
99 demux_sys_t
*sys
= demux
->p_sys
;
101 if (sys
->next_time
== VLC_TS_INVALID
) /* Master mode */
102 return DemuxOnce (demux
, true);
105 while (sys
->next_time
> date_Get (&sys
->date
))
107 int val
= DemuxOnce (demux
, false);
114 static int Control (demux_t
*demux
, int query
, va_list args
)
116 demux_sys_t
*sys
= demux
->p_sys
;
120 case DEMUX_GET_POSITION
:
121 *va_arg (args
, float *) = 0.f
;
124 case DEMUX_GET_LENGTH
:
125 *va_arg (args
, int64_t *) = INT64_C(0);
129 *va_arg (args
, int64_t *) = date_Get (&sys
->date
);
133 date_Set (&sys
->date
, va_arg (args
, int64_t));
136 case DEMUX_SET_NEXT_DEMUX_TIME
:
138 const mtime_t pts
= va_arg (args
, int64_t );
140 if (sys
->next_time
== VLC_TS_INVALID
) /* first invocation? */
142 date_Set (&sys
->date
, pts
);
143 date_Decrement (&sys
->date
, 1);
145 sys
->next_time
= pts
;
149 case DEMUX_GET_PTS_DELAY
:
151 int64_t *v
= va_arg (args
, int64_t *);
152 *v
= INT64_C(1000) * var_InheritInteger (demux
, "live-caching");
156 case DEMUX_CAN_PAUSE
:
157 case DEMUX_CAN_CONTROL_PACE
:
159 *va_arg (args
, bool *) = true;
168 static int Open (vlc_object_t
*obj
)
170 demux_t
*demux
= (demux_t
*)obj
;
171 demux_sys_t
*sys
= malloc (sizeof (*sys
));
173 if (unlikely(sys
== NULL
))
177 es_format_Init (&fmt
, SPU_ES
, VLC_CODEC_ITU_T140
);
178 sys
->es
= es_out_Add (demux
->out
, &fmt
);
181 if (var_InheritURational (demux
, &num
, &den
, "timecode-fps")
184 msg_Err (demux
, "invalid frame rate");
189 date_Init (&sys
->date
, num
, den
);
190 date_Set (&sys
->date
, VLC_TS_0
);
191 sys
->next_time
= VLC_TS_INVALID
;
194 demux
->pf_demux
= Demux
;
195 demux
->pf_control
= Control
;
199 static void Close (vlc_object_t
*obj
)
201 demux_t
*demux
= (demux_t
*)obj
;
202 demux_sys_t
*sys
= demux
->p_sys
;