1 #include "lib_ccx.h"
2 #include "ccx_common_option.h"
3 
4 // Defined by the maximum number of B-Frames per anchor frame.
5 //#define MAXBFRAMES 50 - from lib_ccx.h
6 //  They can be (temporally) before or after the anchor. Reserve
7 // enough space.
8 //#define SORTBUF (2*MAXBFRAMES+1) - from lib_ccx.h
9 // B-Frames can be (temporally) before or after the anchor
10 
init_hdcc(struct lib_cc_decode * ctx)11 void init_hdcc (struct lib_cc_decode *ctx)
12 {
13 	for (int j=0; j<SORTBUF; j++)
14 	{
15 		ctx->cc_data_count[j] = 0;
16 		ctx->cc_fts[j] = 0;
17 	}
18 	memset(ctx->cc_data_pkts, 0, SORTBUF*(31*3+1));
19 	ctx->has_ccdata_buffered = 0;
20 }
21 
22 // Buffer caption blocks for later sorting/flushing.
store_hdcc(struct lib_cc_decode * ctx,unsigned char * cc_data,int cc_count,int sequence_number,LLONG current_fts_now,struct cc_subtitle * sub)23 void store_hdcc(struct lib_cc_decode *ctx, unsigned char *cc_data, int cc_count, int sequence_number, LLONG current_fts_now, struct cc_subtitle *sub)
24 {
25 	//stream_mode = ctx->demux_ctx->get_stream_mode(ctx->demux_ctx);
26 	// Uninitialized?
27 	if (ctx->anchor_seq_number < 0)
28 	{
29 		anchor_hdcc( ctx, sequence_number);
30 	}
31 
32 	int seq_index = sequence_number - ctx->anchor_seq_number + MAXBFRAMES;
33 
34 	if (seq_index < 0 || seq_index > 2*MAXBFRAMES)
35 	{
36 		// Maybe missing an anchor frame - try to recover
37 		dbg_print(CCX_DMT_VERBOSE, "Too many B-frames, or missing anchor frame. Trying to recover ..\n");
38 
39 		process_hdcc(ctx, sub);
40 		anchor_hdcc( ctx, sequence_number);
41 		seq_index = sequence_number - ctx->anchor_seq_number + MAXBFRAMES;
42 	}
43 
44 	ctx->has_ccdata_buffered = 1;
45 
46 	// In GOP mode the fts is set only once for the whole GOP. Recreate
47 	// the right time according to the sequence number.
48 	if (ccx_options.use_gop_as_pts==1)
49 	{
50 		current_fts_now += (LLONG) (sequence_number*1000.0/current_fps);
51 	}
52 
53 	if (cc_count)
54 	{
55 		if (cc_data)
56 		{
57 			// Changed by CFS to concat, i.e. don't assume there's no data already for this seq_index.
58 			// Needed at least for MP4 samples. // TODO: make sure we don't overflow
59 			ctx->cc_fts[seq_index] = current_fts_now; // CFS: Maybe do even if there's no data?
60 			//if (stream_mode!=CCX_SM_MP4) // CFS: Very ugly hack, but looks like overwriting is needed for at least some ES
61 				ctx->cc_data_count[seq_index]  = 0;
62 			memcpy(ctx->cc_data_pkts[seq_index] + ctx->cc_data_count[seq_index] * 3, cc_data, cc_count * 3 + 1);
63 		}
64 		ctx->cc_data_count[seq_index] += cc_count;
65 	}
66 	// DEBUG STUFF
67 	/*
68 	   printf("\nCC blocks, channel 0:\n");
69 	   for ( int i=0; i < cc_count*3; i+=3)
70 	   {
71 	   printf("%s", debug_608_to_ASC( cc_data+i, 0) );
72 	   }
73 	   printf("\n");
74 	 */
75 }
76 
77 // Set a new anchor frame that new B-frames refer to.
anchor_hdcc(struct lib_cc_decode * ctx,int seq)78 void anchor_hdcc(struct lib_cc_decode *ctx, int seq)
79 {
80 	// Re-init the index
81 	ctx->anchor_seq_number = seq;
82 }
83 
84 // Sort/flash caption block buffer
process_hdcc(struct lib_cc_decode * ctx,struct cc_subtitle * sub)85 void process_hdcc (struct lib_cc_decode *ctx, struct cc_subtitle *sub)
86 {
87 	// Remember the current value
88 	LLONG store_fts_now = ctx->timing->fts_now;
89 	int reset_cb = -1;
90 
91 	dbg_print(CCX_DMT_VERBOSE, "Flush HD caption blocks\n");
92 
93 	for (int seq=0; seq<SORTBUF; seq++)
94 	{
95 
96 		// We rely on this.
97 		if (ctx->in_bufferdatatype == CCX_H264)
98 			reset_cb = 1;
99 
100 		// If fts_now is unchanged we rely on cc block counting,
101 		// otherwise reset counters as they get changed by do_cb()
102 		// below. This only happens when current_pts does not get
103 		// updated, like it used do happen for elementary streams.
104 		// Since use_gop_as_pts this is not needed anymore, but left
105 		// here for posterity.
106 		if (reset_cb < 0 && ctx->cc_fts[seq] && seq<SORTBUF-1 && ctx->cc_fts[seq+1])
107 		{
108 			if (ctx->cc_fts[seq] != ctx->cc_fts[seq+1])
109 				reset_cb = 1;
110 			else
111 				reset_cb = 0;
112 		}
113 		if (reset_cb == 1)
114 		{
115 			cb_field1 = 0;
116 			cb_field2 = 0;
117 			cb_708 = 0;
118 		}
119 
120 		// Skip sequence numbers without data
121 		if (ctx->cc_data_count[seq] == 0)
122 			continue;
123 
124 		if (ctx->cc_data_pkts[seq][ctx->cc_data_count[seq]*3]!=0xFF)
125 		{
126 			// This is not optional. Something is wrong.
127 			dbg_print(CCX_DMT_VERBOSE, "Missing 0xFF marker at end\n");
128 			// A "continue;" here would ignore this caption, but we
129 			// process it.
130 		}
131 
132 		// Re-create original time
133 		ctx->timing->fts_now = ctx->cc_fts[seq];
134 		process_cc_data( ctx, ctx->cc_data_pkts[seq], ctx->cc_data_count[seq], sub);
135 
136 	}
137 
138 	// Restore the value
139 	ctx->timing->fts_now = store_fts_now;
140 
141 	// Now that we are done, clean up.
142 	init_hdcc(ctx);
143 }
144