?? fileplayer.c
字號:
#define ALLOW_OS_CODE 1#include "../samples/common.h"#include "../rmdef/rmdef.h"#include "../rmlibcw/include/rmfile.h"#include "../samples/rminputstream.h"#include "../rmproperties/include/rmexternalproperties.h"#include "../rmdetectorapi/include/rmdetectorapi.h"#include "../rmvdemux/include/rmvdemuxapi.h"#include "../rmasfdemux/include/rmasfdemuxapi.h"#include "../rmavicore/include/rmavipushapi.h"#if 1#define LOCALDBG ENABLE#else#define LOCALDBG DISABLE#endif/* #### Begin CARDEA code #### */#include "rmupnp/rmlibwmdrmnd/include/ms_cardea.h"/* #### End CARDEA code #### */#define ERROR_CLEANUP(i) do { error = (i); goto cleanup; } while(0)#define VIDEO_KEYFLAGS (SET_KEY_PLAYBACK)#define AUDIO_KEYFLAGS (SET_KEY_PLAYBACK | SET_KEY_AUDIO)#define AUDIO_VIDEO_KEYFLAGS (SET_KEY_PLAYBACK | SET_KEY_AUDIO)struct detection_callback_info{ RMdetectorHandle detector; RMuint32 parsedBytes; RMuint64 last_pts; RMuint64 first_pts; RMbool audio_detected; RMbool pcm_detected; eAudioFormat_type audio_type; RMuint32 audio_channels; RMuint32 audio_freq; RMuint32 audio_depth; RMuint32 audio_bitrate;};#define AUDIO_DETECTION_THRESHOLD (64 * 1024)// jpeg header parsing reads: // SOF to get the width and height and determine color subsample scheme based on the sample factors// EXIF APP1 to get the orientation of the jpeg picture as in enum PictureOrientation#define EXIFDBG DISABLE#define JPEGDBG DISABLE#define EXIF_MAX_IFD0_SIZE 16*12+2 /*ifd0 contains a max of 16 entries*/enum exifAlign{ intel_align = 0, motorola_align};static inline RMuint32 readExif32(RMuint8* buf, enum exifAlign align){ if(align == motorola_align) return RMbeBufToUint32(buf); return RMleBufToUint32(buf);}static inline RMuint32 readExif16(RMuint8* buf, enum exifAlign align){ if(align == motorola_align) return RMbeBufToUint16(buf); return RMleBufToUint16(buf);}#define JPEG_MAX_MARKER_SIZE 0x10000#define JPEG_MAX_COLOR_COMP 4typedef enum { // JPEG markers JPEG_MARKER_SOF0 = 0xc0, JPEG_MARKER_SOF1 = 0xc1, JPEG_MARKER_SOF2 = 0xc2, JPEG_MARKER_SOF3 = 0xc3, JPEG_MARKER_SOF5 = 0xc5, JPEG_MARKER_SOF6 = 0xc6, JPEG_MARKER_SOF7 = 0xc7, JPEG_MARKER_JPG = 0xc8, JPEG_MARKER_SOF9 = 0xc9, JPEG_MARKER_SOF10 = 0xca, JPEG_MARKER_SOF11 = 0xcb, JPEG_MARKER_SOF13 = 0xcd, JPEG_MARKER_SOF14 = 0xce, JPEG_MARKER_SOF15 = 0xcf, JPEG_MARKER_DHT = 0xc4, JPEG_MARKER_DAC = 0xcc, JPEG_MARKER_RST0 = 0xd0, JPEG_MARKER_RST1 = 0xd1, JPEG_MARKER_RST2 = 0xd2, JPEG_MARKER_RST3 = 0xd3, JPEG_MARKER_RST4 = 0xd4, JPEG_MARKER_RST5 = 0xd5, JPEG_MARKER_RST6 = 0xd6, JPEG_MARKER_RST7 = 0xd7, JPEG_MARKER_SOI = 0xd8, JPEG_MARKER_EOI = 0xd9, JPEG_MARKER_SOS = 0xda, JPEG_MARKER_DQT = 0xdb, JPEG_MARKER_DNL = 0xdc, JPEG_MARKER_DRI = 0xdd, JPEG_MARKER_DHP = 0xde, JPEG_MARKER_EXP = 0xdf, JPEG_MARKER_APP0 = 0xe0, JPEG_MARKER_APP1 = 0xe1, JPEG_MARKER_APP2 = 0xe2, JPEG_MARKER_APP3 = 0xe3, JPEG_MARKER_APP4 = 0xe4, JPEG_MARKER_APP5 = 0xe5, JPEG_MARKER_APP6 = 0xe6, JPEG_MARKER_APP7 = 0xe7, JPEG_MARKER_APP8 = 0xe8, JPEG_MARKER_APP9 = 0xe9, JPEG_MARKER_APP10 = 0xea, JPEG_MARKER_APP11 = 0xeb, JPEG_MARKER_APP12 = 0xec, JPEG_MARKER_APP13 = 0xed, JPEG_MARKER_APP14 = 0xee, JPEG_MARKER_APP15 = 0xef, JPEG_MARKER_JPG0 = 0xf0, JPEG_MARKER_JPG13 = 0xfd, JPEG_MARKER_COM = 0xfe, JPEG_MARKER_TEM = 0x01, JPEG_MARKER_ERROR = 0x100} JPEG_MARKER;static RMstatus jpeg_header_skip_marker( RMfile file, RMuint32 * byte_count ) { RMuint8 buf[2]; RMuint32 read; RMuint32 length; RMstatus err; err = RMReadFile(file, buf, 2, &read); // get the length if(RMFAILED(err) || (read!=2)) { RMDBGLOG((JPEGDBG, "jpeg_header_skip_marker Error reading file\n")); return RM_ERROR; } length = ((RMuint32)buf[0]<<8) + buf[1]; RMDBGLOG((JPEGDBG, "jpeg_header_skip_marker length %d (0x%x 0x%x)\n", length, buf[0], buf[1] )); if( length <2 ) { RMDBGLOG((JPEGDBG, "jpeg_header_skip_marker bad length\n")); return RM_ERROR; } *byte_count += length; length -= 2; while( length != 0 ) { if( length < JPEG_MAX_MARKER_SIZE ) { err = RMSeekFile(file, length, RM_FILE_SEEK_CURRENT); length = 0; } else { err = RMSeekFile(file, JPEG_MAX_MARKER_SIZE, RM_FILE_SEEK_CURRENT); length -= JPEG_MAX_MARKER_SIZE; } if(RMFAILED(err)) { RMDBGLOG((JPEGDBG, "jpeg_header_skip_marker Error reading file size=%d\n", length)); return RM_ERROR; } } return RM_OK;}// process SOF markerstatic RMstatus jpeg_header_get_sof( RMfile file, RMuint32 * width, RMuint32 * height, RMuint32 *profile, RMuint32 * byte_count ) { RMuint8 buf[JPEG_MAX_MARKER_SIZE]; RMuint8* p; RMuint32 read = 0; RMuint32 length; RMstatus err; RMuint32 precision; RMuint32 components; RMuint32 i; RMuint32 component_id[JPEG_MAX_COLOR_COMP]; RMuint32 h_samp_factor[JPEG_MAX_COLOR_COMP]; RMuint32 v_samp_factor[JPEG_MAX_COLOR_COMP]; RMuint32 quant_table[JPEG_MAX_COLOR_COMP]; err = RMReadFile(file, buf, 2, &read); // get the length if(RMFAILED(err) || (read!= 2)) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof Error reading file\n")); return RM_ERROR; } length = ((RMuint32)buf[0]<<8) + buf[1]; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof sof length %d (0x%x 0x%x)\n", length, buf[0], buf[1])); if( length <2 ) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof bad length\n")); return RM_ERROR; } *byte_count += length; length -= 2; err = RMReadFile(file, buf, length, &read); // get marker data if(RMFAILED(err) || (read!= length)) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof Error reading file size=%d\n", length)); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p = buf; precision = (RMuint32)(p[0]); p++; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof precision %d \n", precision)); *height = ((RMuint32)p[0]<<8) + p[1]; p+=2; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof height %d \n", *height)); *width = ((RMuint32)p[0]<<8) + p[1]; p+=2; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof width %d \n", *width)); components = (RMuint32)(p[0]); p++; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof components %d \n", components)); if( length-6 != components * 3) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof bad length =%d\n", length)); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } if( components > JPEG_MAX_COLOR_COMP ) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof too many colors =%d\n", components)); components = JPEG_MAX_COLOR_COMP; // can only handle this many } for( i = 0; i < components; i++ ) { component_id[i] = *p; p++; h_samp_factor[i] = (*p >> 4) & 0x0f; v_samp_factor[i] = (*p) & 0x0f; p++; quant_table[i] = *p; p++; RMDBGLOG((JPEGDBG, "jpeg_header_get_sof components %d hs %d vs %d\n", component_id[i], h_samp_factor[i], v_samp_factor[i] )); } if( components == 3 ) { // only detect the 3 color component pitures if( component_id[0] == 82 && component_id[1] == 71 && component_id[2] == 66 ) { //assume this is RGB color RMDBGLOG((JPEGDBG, "jpeg_header_get_sof rgb color \n" )); *profile = EMhwlib_JPEG_Max_Profile; // no subsampling } else { // rest assume to be YCbCr if( h_samp_factor[1] != h_samp_factor[2] || v_samp_factor[1] != v_samp_factor[2] ) { RMDBGLOG((JPEGDBG, "jpeg_header_get_sof Cb Cr have different sample factor Cb %d %d Cr %d %d\n", h_samp_factor[1], v_samp_factor[1], h_samp_factor[2], v_samp_factor[2] )); return RM_ERROR; } if( (h_samp_factor[0] == 2) && (v_samp_factor[0] == 2 ) && (h_samp_factor[1] == 1) && (v_samp_factor[1] == 1 ) ) *profile = EMhwlibJPEGProfile_2211; else if( (h_samp_factor[0] == 1) && (v_samp_factor[0] == 1 ) && (h_samp_factor[1] == 1) && (v_samp_factor[1] == 1 ) ) *profile = EMhwlibJPEGProfile_2222; else if( (h_samp_factor[0] == 2) && (v_samp_factor[0] == 1 ) && (h_samp_factor[1] == 1) && (v_samp_factor[1] == 1 ) ) *profile = EMhwlibJPEGProfile_2111; else if( (h_samp_factor[0] == 1) && (v_samp_factor[0] == 2 ) && (h_samp_factor[1] == 1) && (v_samp_factor[1] == 1 ) ) *profile = EMhwlibJPEGProfile_1211; else if( (h_samp_factor[0] == 2) && (v_samp_factor[0] == 2 ) && (h_samp_factor[1] == 1) && (v_samp_factor[1] == 2 ) ) *profile = EMhwlibJPEGProfile_2212; else if( (h_samp_factor[0] == 2) && (v_samp_factor[0] == 2 ) && (h_samp_factor[1] == 2) && (v_samp_factor[1] == 1 ) ) *profile = EMhwlibJPEGProfile_2221; else *profile = EMhwlibJPEGProfile_Unknown; } } return RM_OK;}// process EXIF APP1 markerstatic RMstatus jpeg_header_get_app1( RMfile file, RMuint32 *orientation, RMuint32 * byte_count ) { RMstatus err; enum exifAlign align = motorola_align; RMuint8 buf[JPEG_MAX_MARKER_SIZE]; RMuint8 *p = 0; RMuint32 read; RMuint32 length; RMuint32 tmp32; RMuint16 tmp16; RMuint32 i; RMDBGLOG((JPEGDBG, "jpeg_header_get_app1\n")); err = RMReadFile(file, buf, 2, &read); // get the length if(RMFAILED(err) || (read!= 2)) { RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error reading file\n")); return RM_ERROR; } length = ((RMuint32)buf[0]<<8) + buf[1]; RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 length %d (0x%x 0x%x)\n", length, buf[0], buf[1])); if( length <2 ) { RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 bad length\n")); return RM_ERROR; } *byte_count += length; length -= 2; err = RMReadFile(file, buf, 14, &read); // get marker data if(RMFAILED(err) || (read!= 14)) { RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error reading file size=%d\n", length)); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p = buf; // check the app1 data id if( p[0] != 0x45 || p[1] != 0x78 || p[2] != 0x69 || p[3] != 0x66 || p[4] != 0x00 || p[5] != 0x00 ) { RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error while parsing APP1 data chunk\n")); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p+=6; switch( readExif16(p, align) ) { case 0x4949: // intel (little endian) RMDBGLOG((JPEGDBG, "JPEG: INTEL ALIGN (little endian)\n")); align = intel_align; break; case 0x4d4d: // motorola (big endian) RMDBGLOG((JPEGDBG, "JPEG: MOTOROLA ALIGN (big endian)\n")); align = motorola_align; break; default: RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error while parsing endian\n")); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p+=2; if( readExif16(p, align) != 0x002a) { //0x002a tag RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error while parsing 2a tag\n")); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p+=2; tmp32 = readExif32(p, align); p+=4; // offset to IFD if(tmp32 != 8){ RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 skipping %ld extra bytes\n", tmp32-8)); err = RMSeekFile( file, tmp32-8, RM_FILE_SEEK_CURRENT); if(RMFAILED(err)){ RMDBGLOG((JPEGDBG, "Error seeking file\n")); return RM_ERROR; } } err = RMReadFile( file, buf, EXIF_MAX_IFD0_SIZE, &read ); if(RMFAILED(err) || (read!= EXIF_MAX_IFD0_SIZE)){ RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Error reading file\n")); RMSeekFile( file, *byte_count, RM_FILE_SEEK_START ); return RM_ERROR; } p = buf; tmp16 = readExif16(p, align); p+=2; /*ifd number of entries*/ RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 Number of entries is %d\n", tmp16)); if(tmp16 >16) RMDBGLOG((JPEGDBG, "jpeg_header_get_app1 number of entries > 16\n", tmp16)); for (i = 0; i<tmp16; i++) { // each entry is tag(2):data_format(2):num_components(4):data_or_offset(4) RMuint16 tag, format; RMuint32 comp_count, offset; tag = readExif16(p, align); p+=2; format = readExif16(p, align); p+=2; comp_count = readExif32(p, align); p+=4; offset = readExif32(p, align); p+=4; RMDBGLOG((EXIFDBG, "TAG: 0x%04x\n", tag)); switch(tag){ case 0x0112: // orientation if((format != 3) || (comp_count != 1)){ RMDBGLOG((JPEGDBG, "Wrong marker\n")); return RM_ERROR; } if(align == motorola_align) *orientation = (offset>>16) & 0xffff; else *orientation = (offset & 0xffff); RMDBGLOG((JPEGDBG, "ORIENTATION: 0x%08lx\n", *orientation)); break; default: break; } } return RMSeekFile( file, *byte_count, RM_FILE_SEEK_START );}static RMstatus detect_jpeg_header_info( RMfile file, RMuint32 * width, RMuint32 * height, RMuint32 * profile, enum PictureOrientation *orientation ){ RMuint8 header[2]; RMuint32 read_size; RMstatus err; RMbool more_marker = FALSE; RMuint32 marker_count = 0; RMuint32 byte_count = 0; if( ! file ){ RMDBGLOG((JPEGDBG, "detect_jpeg_header_info file %x not opened \n", file )); return RM_ERROR; } // wind the file to the beginning err = RMSeekFile( file, 0, RM_FILE_SEEK_START ); if(RMFAILED(err)){ RMDBGLOG((JPEGDBG, "detect_jpeg_header_info Error seeking file\n")); return RM_ERROR; } //read first marker jpeg is identified by 0xffd8 err = RMReadFile(file, header, 2, &read_size); // get 2 bytes if(RMFAILED(err) || (read_size!= 2)){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -