1
/* readpic.c, read source pictures */
3
/* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
6
* Disclaimer of Warranty
8
* These software programs are available to the user without any license fee or
9
* royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
10
* any and all warranties, whether express, implied, or statuary, including any
11
* implied warranties or merchantability or of fitness for a particular
12
* purpose. In no event shall the copyright-holder be liable for any
13
* incidental, punitive, or consequential damages of any kind whatsoever
14
* arising from the use of these programs.
16
* This disclaimer of warranty extends to the user of these programs and user's
17
* customers, employees, agents, transferees, successors, and assigns.
19
* The MPEG Software Simulation Group does not represent or warrant that the
20
* programs furnished hereunder are free of infringement of any third-party
23
* Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24
* are subject to royalty fees to patent holders. Many of these patents are
25
* general enough such that they are unavoidable regardless of implementation
29
/* Modifications and enhancements (C) 2000/2001 Andrew Stevens */
31
/* These modifications are free software; you can redistribute it
32
* and/or modify it under the terms of the GNU General Public License
33
* as published by the Free Software Foundation; either version 2 of
34
* the License, or (at your option) any later version.
36
* This program is distributed in the hope that it will be useful,
37
* but WITHOUT ANY WARRANTY; without even the implied warranty of
38
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
* General Public License for more details.
41
* You should have received a copy of the GNU General Public License
42
* along with this program; if not, write to the Free Software
43
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
48
/* Modifications and enhancements
49
(C) 2000/2001 Andrew Stevens, Rainer Johanni
53
/* These modifications are free software; you can redistribute it
54
* and/or modify it under the terms of the GNU General Public License
55
* as published by the Free Software Foundation; either version 2 of
56
* the License, or (at your option) any later version.
58
* This program is distributed in the hope that it will be useful,
59
* but WITHOUT ANY WARRANTY; without even the implied warranty of
60
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
61
* General Public License for more details.
63
* You should have received a copy of the GNU General Public License
64
* along with this program; if not, write to the Free Software
65
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
76
//#include <pthread.h>
80
#include "mpegconsts.h"
83
#include "ADM_toolkit/ADM_cpuCap.h"
85
/* NOTE: access toframes_read *must* be read-only in other threads
86
once the chunk-reading worker thread has been started.
90
static volatile int frames_read = 0;
91
static int last_frame = -1;
94
/* Buffers for frame luminance means */
95
int luminance_mean_C(uint8_t *frame, int w, int h );
96
int luminance_mean_MMX(uint8_t *frame, int w, int h );
99
int luminance_mean(uint8_t *frame, int w, int h )
101
#if defined( ARCH_X86) || defined(ARCH_X86_64)
102
if(CpuCaps::hasMMX()) return luminance_mean_MMX(frame,w,h);
104
luminance_mean_C(frame,w,h);
111
int luminance_mean_C(uint8_t *frame, int w, int h )
114
uint8_t *lim = frame + w*h;
118
sum += (p[0] + p[1]) + (p[2] + p[3]) + (p[4] + p[5]) + (p[6] + p[7]);
124
#if defined( ARCH_X86) || defined(ARCH_X86_64)
126
// code borrowed from ffmpeg by means
128
static int pix_sum16_mmx(uint8_t * pix, int line_size)
132
long int rline_size=line_size;
134
long int index= -line_size*h;
136
int rline_size=line_size;
138
int index= -line_size*h;
142
"pxor %%mm7, %%mm7 \n\t"
143
"pxor %%mm6, %%mm6 \n\t"
145
"movq (%2, %1), %%mm0 \n\t"
146
"movq (%2, %1), %%mm1 \n\t"
147
"movq 8(%2, %1), %%mm2 \n\t"
148
"movq 8(%2, %1), %%mm3 \n\t"
149
"punpcklbw %%mm7, %%mm0 \n\t"
150
"punpckhbw %%mm7, %%mm1 \n\t"
151
"punpcklbw %%mm7, %%mm2 \n\t"
152
"punpckhbw %%mm7, %%mm3 \n\t"
153
"paddw %%mm0, %%mm1 \n\t"
154
"paddw %%mm2, %%mm3 \n\t"
155
"paddw %%mm1, %%mm3 \n\t"
156
"paddw %%mm3, %%mm6 \n\t"
159
"movq %%mm6, %%mm5 \n\t"
160
"psrlq $32, %%mm6 \n\t"
161
"paddw %%mm5, %%mm6 \n\t"
162
"movq %%mm6, %%mm5 \n\t"
163
"psrlq $16, %%mm6 \n\t"
164
"paddw %%mm5, %%mm6 \n\t"
165
"movd %%mm6, %0 \n\t"
166
"and $0xFFFF, %0 \n\t"
167
: "=&r" (sum), "+r" (index)
168
: "r" (pix - index), "r" (rline_size)
173
int luminance_mean_MMX(uint8_t *frame, int w, int h )
185
mean+=pix_sum16_mmx(p, w);
197
int piperead(int fd, uint8_t *buf, int len)
205
n = read(fd,buf+r,len-r);
216
static void read_chunk(void)
222
for(j=0;j<READ_CHUNK_SIZE;++j)
224
if( ctl->parallel_read )
226
// Unlock during the actual I/O filling buffers to allow
227
// the main thread to run if there are still the frames
228
// it needs. The main thread atomically signals new_chunk_req
229
// before waiting on new_chunk_ack.
230
// This thread atomically signals new_chunk_ack before
231
// waiting on new_chunk_req.
232
// Thus neither can suspend without first
233
// starting the other.
234
//mjpeg_info( "PRO: releasing frame buf lock @ %d ", frames_read);
236
pthread_mutex_unlock( &frame_buffer_lock );
238
n = frames_read % frame_buffer_size;
240
y4m_init_frame_info (&fi);
242
if ((y = y4m_read_frame_header (istrm_fd, &fi)) != Y4M_OK)
244
if( y != Y4M_ERR_EOF )
246
"Error reading frame header (%d): code%s!",
252
v = opt->vertical_size;
253
h = opt->horizontal_size;
255
if(piperead(istrm_fd,frame_buffers[n][0]+i*opt->phy_width,h)!=h) goto EOF_MARK;
256
lum_mean[n] = luminance_mean(frame_buffers[n][0], opt->phy_width, opt->phy_height );
258
v = opt->chroma_format==CHROMA420 ?
259
opt->vertical_size/2 : opt->vertical_size;
260
h = opt->chroma_format!=CHROMA444 ?
261
opt->horizontal_size/2 : opt->horizontal_size;
263
if(piperead(istrm_fd,frame_buffers[n][1]+i*opt->phy_chrom_width,h)!=h) goto EOF_MARK;
265
if(piperead(istrm_fd,frame_buffers[n][2]+i*opt->phy_chrom_width,h)!=h) goto EOF_MARK;
268
if( ctl->parallel_read )
271
// Lock to atomically signal the availability of additional
272
// material from a chunk - waking the main thread
273
// if it suspended because a required frame was
276
//mjpeg_info( "PRO: waiting for frame buf lock @ %d ", frames_read);
277
pthread_mutex_lock( &frame_buffer_lock );
281
if( ctl->parallel_read )
283
//mjpeg_info( "PRO: Signalling new_chunk_ack @ %d", frames_read );
284
pthread_cond_broadcast( &new_chunk_ack );
290
// When we exit we're holding the lock again so we can
291
// ensure we're waiting on new_chunk_req if the main thread is
292
// currently running.
297
mjpeg_debug( "End of input stream detected" );
298
if( ctl->parallel_read )
300
pthread_mutex_lock( &frame_buffer_lock );
302
last_frame = frames_read-1;
303
istrm_nframes = frames_read;
304
//mjpeg_info( "Signalling last frame = %d", last_frame );
305
if( ctl->parallel_read )
307
//mjpeg_info( "PRO: Signalling new_chunk_ack @ %d", frames_read );
308
pthread_cond_broadcast( &new_chunk_ack );
316
static void *read_chunks_worker(void *_dummy)
318
//mjpeg_info("PRO: requesting frame buf lock" );
319
//mjpeg_info( "PRO: has frame buf lock @ %d ", frames_read );
320
//mjpeg_info( "PRO: Initial fill of frame buf" );
321
pthread_mutex_lock( &frame_buffer_lock );
325
//mjpeg_info( "PRO: has frame buf lock @ %d ", frames_read );
326
//mjpeg_info( "PRO: Waiting for new_chunk_req " );
327
pthread_cond_wait( &new_chunk_req, &frame_buffer_lock );
328
//mjpeg_info( "PRO: new_chunk_req regained frame buf lock @ %d ", frames_read );
329
if( frames_read < istrm_nframes )
338
static void start_worker(void)
340
pthread_attr_t *pattr = NULL;
342
#ifdef HAVE_PTHREADSTACKSIZE
343
#define MINSTACKSIZE 200000
347
pthread_attr_init(&attr);
348
pthread_attr_getstacksize(&attr, &stacksize);
350
if (stacksize < MINSTACKSIZE) {
351
pthread_attr_setstacksize(&attr, MINSTACKSIZE);
358
if( pthread_create( &worker_thread, pattr, read_chunks_worker, NULL ) != 0 )
360
mjpeg_error_exit1( "worker thread creation failed: %s", strerror(errno) );
366
/*****************************************************
368
* Read another chunk of frames into the frame buffer if the
369
* specified frame is less than a chunk away from the end of the
370
* buffer. This version is for when frame input reading is not
371
* multi-threaded and just goes ahead and does it.
373
* N.b. if ctl->parallel_read is active then read_chunk signals/locks
374
* which could cause problems hence the assert!
376
*****************************************************/
378
static void read_chunk_seq( int num_frame )
380
while(frames_read - num_frame < READ_CHUNK_SIZE &&
381
frames_read < istrm_nframes )
387
/*****************************************************
389
* Request read worker thread to read a chunk of frame into the frame
390
* buffer if less than a chunk of frames is left after the specified
391
* frame. Wait for acknowledgement of the reading of a chunk (implying
392
* at least one extra frame added to the buffer) if the specified frame
393
* is not yet in the buffer.
395
* N.b. *must* be called with ctl->parallel_read active as otherwise it
396
* will thoroughly deadlocked.
398
*****************************************************/
402
static void read_chunk_par( int num_frame)
404
//mjpeg_info( "CON: requesting frame buf lock");
405
pthread_mutex_lock( &frame_buffer_lock);
408
//mjpeg_info( "CON: has frame buf lock @ %d (%d recorded read)", frames_read, num_frame );
409
// Activate reader process "on the fly"
410
if( frames_read - num_frame < READ_CHUNK_SIZE &&
411
frames_read < istrm_nframes )
413
//mjpeg_info( "CON: Running low on frames: signalling new_chunk_req" );
415
pthread_cond_broadcast( &new_chunk_req );
417
if( frames_read > num_frame ||
418
frames_read >= istrm_nframes )
420
//mjpeg_info( "CON: releasing frame buf lock - enough frames to go on with...");
421
pthread_mutex_unlock( &frame_buffer_lock );
424
//mjpeg_info( "CON: waiting for new_chunk_ack - too few frames" );
425
pthread_cond_wait( &new_chunk_ack, &frame_buffer_lock );
426
//mjpeg_info( "CON: regained frame buf lock @ %d (%d processed)", frames_read, num_frame );
432
static void load_frame( int num_frame )
434
printf("Push %d\n",num_frame);
435
if(last_frame>=0 && num_frame>last_frame &&num_frame<istrm_nframes)
437
mjpeg_error("Internal:readframe: internal error reading beyond end of frames");
441
if( frames_read == 0)
445
pthread_mutexattr_t mu_attr;
446
pthread_mutexattr_t *p_attr = &mu_attr;
447
pthread_mutexattr_settype( &mu_attr, PTHREAD_MUTEX_ERRORCHECK );
450
pthread_mutexattr_t *p_attr = NULL;
452
pthread_mutex_init( &frame_buffer_lock, p_attr );
455
lum_mean = new int[frame_buffer_size];
458
Pre-fill the buffer with one chunk of frames...
460
/* if( ctl->parallel_read )
463
read_chunk_par( num_frame);
467
read_chunk_seq( num_frame);
472
/* Read a chunk of frames if we've got less than one chunk buffered
475
/* if( ctl->parallel_read )
476
read_chunk_par( num_frame );
478
read_chunk_seq( num_frame );
480
/* We aren't allowed to go too far behind the last read
483
if( num_frame+static_cast<int>(frame_buffer_size) < frames_read )
485
mjpeg_error("Internal:readframe: %d internal error - buffer flushed too soon", frame_buffer_size );
488
printf("Pushed %d %d\n",num_frame,frames_read);
492
int readframe( int num_frame,
493
unsigned char *frame[]
498
load_frame( num_frame );
499
n = num_frame % frame_buffer_size;
500
frame[0] = frame_buffers[n][0];
501
frame[1] = frame_buffers[n][1];
502
frame[2] = frame_buffers[n][2];
506
int frame_lum_mean( int num_frame )
509
// printf("lum mean %d\n",num_frame);
511
// We use this function to probe for the existence of frames
512
// so we clip at the end if the end is already found...
514
if( last_frame > 0 && num_frame > last_frame )
520
// We may now know where the last frame is...
522
if( last_frame > 0 && n > last_frame )
524
// printf("lum mean %d\n",n);
525
return lum_mean[n% frame_buffer_size];
530
void read_stream_params( unsigned int *hsize,
532
unsigned int *frame_rate_code,
533
unsigned int *interlacing_code,
534
unsigned int *aspect_ratio_code)
538
y4m_stream_info_t si;
540
y4m_init_stream_info (&si);
541
if ((n = y4m_read_stream_header (istrm_fd, &si)) != Y4M_OK) {
542
mjpeg_log(LOG_ERROR, "Could not read YUV4MPEG2 header: %s!",
547
*hsize = y4m_si_get_width(&si);
548
*vsize = y4m_si_get_height(&si);
549
*frame_rate_code = mpeg_framerate_code(y4m_si_get_framerate(&si));
550
*interlacing_code = y4m_si_get_interlace(&si);
552
/* Deduce MPEG aspect ratio from stream's frame size and SAR...
553
(always as an MPEG-2 code; that's what caller expects). */
554
sar = y4m_si_get_sampleaspect(&si);
555
*aspect_ratio_code = mpeg_guess_mpeg_aspect_code(2, sar,
562
* c-file-style: "stroustrup"
564
* indent-tabs-mode: nil