提交 4eb106a7 编写于 作者: Z zccicy

videotoolbox support

上级 f25f6ece
......@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
45D57D611A53233200BDD389 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45D57D601A53233200BDD389 /* CoreVideo.framework */; };
45D57D631A53233800BDD389 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45D57D621A53233800BDD389 /* VideoToolbox.framework */; };
E60E8C2A19EF70BB005B5B6E /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E60E8C2919EF70BB005B5B6E /* CoreMedia.framework */; };
E60FFBE418BF695700825D7F /* libIJKMediaPlayer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E6D74F2E18A5F94B00165BFD /* libIJKMediaPlayer.a */; };
E612EAE517F7E0F800BEE660 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E612EAE417F7E0F800BEE660 /* MediaPlayer.framework */; };
......@@ -58,6 +60,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
45D57D601A53233200BDD389 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; };
45D57D621A53233800BDD389 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
E60E8C2719EF70A7005B5B6E /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
E60E8C2919EF70BB005B5B6E /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
E612EAE417F7E0F800BEE660 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
......@@ -103,6 +107,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
45D57D631A53233800BDD389 /* VideoToolbox.framework in Frameworks */,
45D57D611A53233200BDD389 /* CoreVideo.framework in Frameworks */,
E60E8C2A19EF70BB005B5B6E /* CoreMedia.framework in Frameworks */,
E61B45AE19EF7021002792EC /* AVFoundation.framework in Frameworks */,
E60FFBE418BF695700825D7F /* libIJKMediaPlayer.a in Frameworks */,
......@@ -166,6 +172,8 @@
E6903EFE17EAF70200CFD954 /* Frameworks */ = {
isa = PBXGroup;
children = (
45D57D621A53233800BDD389 /* VideoToolbox.framework */,
45D57D601A53233200BDD389 /* CoreVideo.framework */,
E63FC29917F062E8003551EB /* libbz2.dylib */,
E63FC29517F060A7003551EB /* libz.dylib */,
E63FC28F17F04C83003551EB /* AudioToolbox.framework */,
......
......@@ -39,7 +39,7 @@
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:NO];
NSURL *theMovieURL = [NSURL URLWithString:@"http://wshdl.acgvideo.com/live/live_5099_3038_d0ffe541.flv"];
NSURL *theMovieURL = [NSURL URLWithString:@"http://vhotwsh.video.qq.com/flv/32/146/r0015d10iwu.p203.1.mp4?vkey=68023055CEC9CC9E1D988B0E71E4B58C38B0374F1CB9805F4A1901D8E87B42137DD9680CF88D3685C3A59F030BAE55AA2E7238551DCB6BFF&fmt=sd&type=mp4"];
[IJKFFMoviePlayerController setLogReport:YES];
self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:theMovieURL withOptions:nil];
......
......@@ -8,6 +8,11 @@
/* Begin PBXBuildFile section */
451103131A5CE36A00337D24 /* IJKSDLGLRenderNV12.m in Sources */ = {isa = PBXBuildFile; fileRef = 451103121A5CE36A00337D24 /* IJKSDLGLRenderNV12.m */; };
454316261A66493700676070 /* ffpipeline_ios.c in Sources */ = {isa = PBXBuildFile; fileRef = 454316201A66493700676070 /* ffpipeline_ios.c */; };
454316271A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.m in Sources */ = {isa = PBXBuildFile; fileRef = 454316231A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.m */; };
454316281A66493700676070 /* ffpipenode_ios_videotoolbox_vout.m in Sources */ = {isa = PBXBuildFile; fileRef = 454316251A66493700676070 /* ffpipenode_ios_videotoolbox_vout.m */; };
4543162B1A66497900676070 /* IJKVideoToolBox.m in Sources */ = {isa = PBXBuildFile; fileRef = 4543162A1A66497900676070 /* IJKVideoToolBox.m */; };
45DB4AAC1A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.m in Sources */ = {isa = PBXBuildFile; fileRef = 45DB4AA81A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.m */; };
E62139BE180FA89B00553533 /* IJKFFOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = E62139BD180FA89A00553533 /* IJKFFOptions.m */; };
E62139BF180FAE5F00553533 /* IJKFFOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = E62139BC180FA89A00553533 /* IJKFFOptions.h */; };
E63FC27117F01143003551EB /* ijksdl_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = E63FC27017F01143003551EB /* ijksdl_audio.c */; };
......@@ -87,6 +92,17 @@
/* Begin PBXFileReference section */
451103111A5CE36A00337D24 /* IJKSDLGLRenderNV12.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJKSDLGLRenderNV12.h; sourceTree = "<group>"; };
451103121A5CE36A00337D24 /* IJKSDLGLRenderNV12.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJKSDLGLRenderNV12.m; sourceTree = "<group>"; };
454316201A66493700676070 /* ffpipeline_ios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ffpipeline_ios.c; path = ijkmedia/ijkplayer/ios/pipeline/ffpipeline_ios.c; sourceTree = "<group>"; };
454316211A66493700676070 /* ffpipeline_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffpipeline_ios.h; path = ijkmedia/ijkplayer/ios/pipeline/ffpipeline_ios.h; sourceTree = "<group>"; };
454316221A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffpipenode_ios_videotoolbox_vdec.h; path = ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vdec.h; sourceTree = "<group>"; };
454316231A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ffpipenode_ios_videotoolbox_vdec.m; path = ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vdec.m; sourceTree = "<group>"; };
454316241A66493700676070 /* ffpipenode_ios_videotoolbox_vout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffpipenode_ios_videotoolbox_vout.h; path = ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vout.h; sourceTree = "<group>"; };
454316251A66493700676070 /* ffpipenode_ios_videotoolbox_vout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ffpipenode_ios_videotoolbox_vout.m; path = ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vout.m; sourceTree = "<group>"; };
454316291A66497900676070 /* IJKVideoToolBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJKVideoToolBox.h; path = ijkmedia/ijkplayer/ios/pipeline/IJKVideoToolBox.h; sourceTree = "<group>"; };
4543162A1A66497900676070 /* IJKVideoToolBox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJKVideoToolBox.m; path = ijkmedia/ijkplayer/ios/pipeline/IJKVideoToolBox.m; sourceTree = "<group>"; };
45DB4AA71A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ijksdl_vout_overlay_videotoolbox.h; sourceTree = "<group>"; };
45DB4AA81A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ijksdl_vout_overlay_videotoolbox.m; sourceTree = "<group>"; };
45DCC8E51A66984200DE441F /* h264_sps_parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = h264_sps_parser.h; sourceTree = "<group>"; };
E62139BC180FA89A00553533 /* IJKFFOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJKFFOptions.h; sourceTree = "<group>"; };
E62139BD180FA89A00553533 /* IJKFFOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJKFFOptions.m; sourceTree = "<group>"; };
E63FC27017F01143003551EB /* ijksdl_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijksdl_audio.c; sourceTree = "<group>"; };
......@@ -289,6 +305,22 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4543161F1A66481600676070 /* pipeline */ = {
isa = PBXGroup;
children = (
454316201A66493700676070 /* ffpipeline_ios.c */,
454316211A66493700676070 /* ffpipeline_ios.h */,
454316221A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.h */,
454316231A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.m */,
454316241A66493700676070 /* ffpipenode_ios_videotoolbox_vout.h */,
454316251A66493700676070 /* ffpipenode_ios_videotoolbox_vout.m */,
454316291A66497900676070 /* IJKVideoToolBox.h */,
4543162A1A66497900676070 /* IJKVideoToolBox.m */,
45DCC8E51A66984200DE441F /* h264_sps_parser.h */,
);
name = pipeline;
sourceTree = "<group>";
};
E63FC27217F013DE003551EB /* dummy */ = {
isa = PBXGroup;
children = (
......@@ -322,6 +354,7 @@
E66F8DF817EFEC1300354D80 /* ios */ = {
isa = PBXGroup;
children = (
4543161F1A66481600676070 /* pipeline */,
E66F8E0117EFEEA400354D80 /* ijkplayer_ios.m */,
E66F8E0217EFEEA400354D80 /* ijkplayer_ios.h */,
);
......@@ -662,6 +695,8 @@
E6EE92AA1878230C009EAB56 /* ijksdl_thread_ios.m */,
E6EE92AB1878230C009EAB56 /* ijksdl_vout_ios_gles2.h */,
E6EE92AC1878230C009EAB56 /* ijksdl_vout_ios_gles2.m */,
45DB4AA71A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.h */,
45DB4AA81A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.m */,
E6EE92C618782770009EAB56 /* IJKSDLAudioKit.h */,
E6EE92C718782770009EAB56 /* IJKSDLAudioKit.m */,
E6EE92C01878236A009EAB56 /* IJKSDLAudioQueueController.h */,
......@@ -765,6 +800,7 @@
E6EE92C818782770009EAB56 /* IJKSDLAudioKit.m in Sources */,
E690403117EAFC6100CFD954 /* ijksdl_stdinc.c in Sources */,
E6EE92BC1878230C009EAB56 /* IJKSDLGLRenderI420.m in Sources */,
45DB4AAC1A5D52AE005CAD41 /* ijksdl_vout_overlay_videotoolbox.m in Sources */,
E690403217EAFC6100CFD954 /* ijksdl_thread.c in Sources */,
E67B91AF1A3801DB00717EA9 /* ff_ffpipeline.c in Sources */,
E67B91B01A3801DB00717EA9 /* ff_ffpipenode.c in Sources */,
......@@ -773,10 +809,12 @@
E690403417EAFC6100CFD954 /* ijksdl_vout.c in Sources */,
E6EE92B91878230C009EAB56 /* ijksdl_thread_ios.m in Sources */,
E66F8DC117EEC65200354D80 /* IJKMPMoviePlayerController.m in Sources */,
4543162B1A66497900676070 /* IJKVideoToolBox.m in Sources */,
E67C4E0819D15EEA00415CEE /* IJKAVMoviePlayerController.m in Sources */,
E6FAD9571A515CE300725002 /* ijkmeta.c in Sources */,
E6EE92B81878230C009EAB56 /* ijksdl_aout_ios_audiounit.m in Sources */,
E6EE92C21878236A009EAB56 /* IJKSDLAudioQueueController.m in Sources */,
454316271A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.m in Sources */,
E67B91BA1A3801E600717EA9 /* ffpipenode_ffplay_vout.c in Sources */,
E66F8DE717EFD9C300354D80 /* IJKFFMoviePlayerController.m in Sources */,
E66F8DF117EFEA9400354D80 /* ijkplayer.c in Sources */,
......@@ -794,9 +832,11 @@
E6EE92BA1878230C009EAB56 /* ijksdl_vout_ios_gles2.m in Sources */,
E6716E4B1807E5FC00B3FBC1 /* IJKMediaUtils.m in Sources */,
E6716E4E1807EA5000B3FBC1 /* IJKFFMrl.m in Sources */,
454316281A66493700676070 /* ffpipenode_ios_videotoolbox_vout.m in Sources */,
E67B91B91A3801E600717EA9 /* ffpipenode_ffplay_vdec.c in Sources */,
451103131A5CE36A00337D24 /* IJKSDLGLRenderNV12.m in Sources */,
E62139BE180FA89B00553533 /* IJKFFOptions.m in Sources */,
454316261A66493700676070 /* ffpipeline_ios.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -440,7 +440,7 @@ inline static void fillMetaInternal(NSMutableDictionary *meta, IjkMediaMeta *raw
const char *value = ijkmeta_get_string_l(rawMeta, name);
if (value) {
[meta setObject:[NSString stringWithUTF8String:value] forKey:key];
} else if (defaultValue){
} else if (defaultValue) {
[meta setObject:defaultValue forKey:key];
} else {
[meta removeObjectForKey:key];
......
......@@ -30,10 +30,12 @@ typedef struct IjkMediaPlayer IjkMediaPlayer;
@property(nonatomic) IJKAVDiscard skipLoopFilter;
@property(nonatomic) IJKAVDiscard skipFrame;
@property(nonatomic) int frameBufferCount;
@property(nonatomic) int maxFps;
@property(nonatomic) int frameDrop;
@property(nonatomic) BOOL pauseInBackground;
@property(nonatomic) int frameBufferCount;
@property(nonatomic) int maxFps;
@property(nonatomic) int frameDrop;
@property(nonatomic) BOOL pauseInBackground;
@property(nonatomic) BOOL videotoolboxEnabled;
@property(nonatomic) int frameMaxWidth;
@property(nonatomic, strong) NSString* userAgent;
......
......@@ -18,13 +18,16 @@
options.skipLoopFilter = IJK_AVDISCARD_ALL;
options.skipFrame = IJK_AVDISCARD_NONREF;
options.frameBufferCount = 3;
options.maxFps = 30;
options.frameDrop = 0;
options.pauseInBackground = YES;
options.frameBufferCount = 3;
options.maxFps = 30;
options.frameDrop = 0;
options.pauseInBackground = YES;
options.timeout = 30 * 1000 * 1000; // 30 seconds
options.userAgent = @"";
options.videotoolboxEnabled = YES;
options.frameMaxWidth = 960;
options.timeout = 30 * 1000 * 1000; // 30 seconds
options.userAgent = @"";
return options;
}
......@@ -43,6 +46,9 @@
ijkmp_set_picture_queue_capicity(mediaPlayer, _frameBufferCount);
ijkmp_set_max_fps(mediaPlayer, _maxFps);
ijkmp_set_framedrop(mediaPlayer, _frameDrop);
ijkmp_ios_set_videotoolbox_enabled(mediaPlayer, _videotoolboxEnabled);
ijkmp_ios_set_frame_max_width(mediaPlayer, _frameMaxWidth);
if (self.timeout > 0) {
[self setFormatOption:@"timeout"
......
/*
* h264_sps_parser.h
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IJKMediaPlayer_h264_sps_parser_h
#define IJKMediaPlayer_h264_sps_parser_h
#define AV_RB16(x) \
((((const uint8_t*)(x))[0] << 8) | \
((const uint8_t*)(x)) [1])
#define AV_RB24(x) \
((((const uint8_t*)(x))[0] << 16) | \
(((const uint8_t*)(x))[1] << 8) | \
((const uint8_t*)(x))[2])
#define AV_RB32(x) \
((((const uint8_t*)(x))[0] << 24) | \
(((const uint8_t*)(x))[1] << 16) | \
(((const uint8_t*)(x))[2] << 8) | \
((const uint8_t*)(x))[3])
typedef struct
{
const uint8_t *data;
const uint8_t *end;
int head;
uint64_t cache;
} nal_bitstream;
static void
nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size)
{
bs->data = data;
bs->end = data + size;
bs->head = 0;
// fill with something other than 0 to detect
// emulation prevention bytes
bs->cache = 0xffffffff;
}
static uint64_t
nal_bs_read(nal_bitstream *bs, int n)
{
uint64_t res = 0;
int shift;
if (n == 0)
return res;
// fill up the cache if we need to
while (bs->head < n) {
uint8_t a_byte;
bool check_three_byte;
check_three_byte = true;
next_byte:
if (bs->data >= bs->end) {
// we're at the end, can't produce more than head number of bits
n = bs->head;
break;
}
// get the byte, this can be an emulation_prevention_three_byte that we need
// to ignore.
a_byte = *bs->data++;
if (check_three_byte && a_byte == 0x03 && ((bs->cache & 0xffff) == 0)) {
// next byte goes unconditionally to the cache, even if it's 0x03
check_three_byte = false;
goto next_byte;
}
// shift bytes in cache, moving the head bits of the cache left
bs->cache = (bs->cache << 8) | a_byte;
bs->head += 8;
}
// bring the required bits down and truncate
if ((shift = bs->head - n) > 0)
res = bs->cache >> shift;
else
res = bs->cache;
// mask out required bits
if (n < 32)
res &= (1 << n) - 1;
bs->head = shift;
return res;
}
static bool
nal_bs_eos(nal_bitstream *bs)
{
return (bs->data >= bs->end) && (bs->head == 0);
}
// read unsigned Exp-Golomb code
static int64_t
nal_bs_read_ue(nal_bitstream *bs)
{
int i = 0;
while (nal_bs_read(bs, 1) == 0 && !nal_bs_eos(bs) && i < 32)
i++;
return ((1 << i) - 1 + nal_bs_read(bs, i));
}
typedef struct
{
uint64_t profile_idc;
uint64_t level_idc;
uint64_t sps_id;
uint64_t chroma_format_idc;
uint64_t separate_colour_plane_flag;
uint64_t bit_depth_luma_minus8;
uint64_t bit_depth_chroma_minus8;
uint64_t qpprime_y_zero_transform_bypass_flag;
uint64_t seq_scaling_matrix_present_flag;
uint64_t log2_max_frame_num_minus4;
uint64_t pic_order_cnt_type;
uint64_t log2_max_pic_order_cnt_lsb_minus4;
uint64_t max_num_ref_frames;
uint64_t gaps_in_frame_num_value_allowed_flag;
uint64_t pic_width_in_mbs_minus1;
uint64_t pic_height_in_map_units_minus1;
uint64_t frame_mbs_only_flag;
uint64_t mb_adaptive_frame_field_flag;
uint64_t direct_8x8_inference_flag;
uint64_t frame_cropping_flag;
uint64_t frame_crop_left_offset;
uint64_t frame_crop_right_offset;
uint64_t frame_crop_top_offset;
uint64_t frame_crop_bottom_offset;
} sps_info_struct;
static void parseh264_sps(uint8_t *sps, uint32_t sps_size, int *level, int *profile, bool *interlaced, int32_t *max_ref_frames)
{
nal_bitstream bs;
sps_info_struct sps_info = {0};
nal_bs_init(&bs, sps, sps_size);
sps_info.profile_idc = nal_bs_read(&bs, 8);
nal_bs_read(&bs, 1); // constraint_set0_flag
nal_bs_read(&bs, 1); // constraint_set1_flag
nal_bs_read(&bs, 1); // constraint_set2_flag
nal_bs_read(&bs, 1); // constraint_set3_flag
nal_bs_read(&bs, 4); // reserved
sps_info.level_idc = nal_bs_read(&bs, 8);
sps_info.sps_id = nal_bs_read_ue(&bs);
if (sps_info.profile_idc == 100 ||
sps_info.profile_idc == 110 ||
sps_info.profile_idc == 122 ||
sps_info.profile_idc == 244 ||
sps_info.profile_idc == 44 ||
sps_info.profile_idc == 83 ||
sps_info.profile_idc == 86)
{
sps_info.chroma_format_idc = nal_bs_read_ue(&bs);
if (sps_info.chroma_format_idc == 3)
sps_info.separate_colour_plane_flag = nal_bs_read(&bs, 1);
sps_info.bit_depth_luma_minus8 = nal_bs_read_ue(&bs);
sps_info.bit_depth_chroma_minus8 = nal_bs_read_ue(&bs);
sps_info.qpprime_y_zero_transform_bypass_flag = nal_bs_read(&bs, 1);
sps_info.seq_scaling_matrix_present_flag = nal_bs_read (&bs, 1);
if (sps_info.seq_scaling_matrix_present_flag)
{
/* TODO: unfinished */
}
}
sps_info.log2_max_frame_num_minus4 = nal_bs_read_ue(&bs);
if (sps_info.log2_max_frame_num_minus4 > 12) {
// must be between 0 and 12
// don't early return here - the bits we are using (profile/level/interlaced/ref frames)
// might still be valid - let the parser go on and pray.
//return;
}
sps_info.pic_order_cnt_type = nal_bs_read_ue(&bs);
if (sps_info.pic_order_cnt_type == 0) {
sps_info.log2_max_pic_order_cnt_lsb_minus4 = nal_bs_read_ue(&bs);
}
else if (sps_info.pic_order_cnt_type == 1) { // TODO: unfinished
/*
delta_pic_order_always_zero_flag = gst_nal_bs_read (bs, 1);
offset_for_non_ref_pic = gst_nal_bs_read_se (bs);
offset_for_top_to_bottom_field = gst_nal_bs_read_se (bs);
num_ref_frames_in_pic_order_cnt_cycle = gst_nal_bs_read_ue (bs);
for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
offset_for_ref_frame[i] = gst_nal_bs_read_se (bs);
*/
}
sps_info.max_num_ref_frames = nal_bs_read_ue(&bs);
sps_info.gaps_in_frame_num_value_allowed_flag = nal_bs_read(&bs, 1);
sps_info.pic_width_in_mbs_minus1 = nal_bs_read_ue(&bs);
sps_info.pic_height_in_map_units_minus1 = nal_bs_read_ue(&bs);
sps_info.frame_mbs_only_flag = nal_bs_read(&bs, 1);
if (!sps_info.frame_mbs_only_flag)
sps_info.mb_adaptive_frame_field_flag = nal_bs_read(&bs, 1);
sps_info.direct_8x8_inference_flag = nal_bs_read(&bs, 1);
sps_info.frame_cropping_flag = nal_bs_read(&bs, 1);
if (sps_info.frame_cropping_flag) {
sps_info.frame_crop_left_offset = nal_bs_read_ue(&bs);
sps_info.frame_crop_right_offset = nal_bs_read_ue(&bs);
sps_info.frame_crop_top_offset = nal_bs_read_ue(&bs);
sps_info.frame_crop_bottom_offset = nal_bs_read_ue(&bs);
}
*level = (int)sps_info.level_idc;
*profile = (int)sps_info.profile_idc;
*interlaced = (int)!sps_info.frame_mbs_only_flag;
*max_ref_frames = (int)sps_info.max_num_ref_frames;
}
bool validate_avcC_spc(uint8_t *extradata, uint32_t extrasize, int32_t *max_ref_frames, int *level, int *profile)
{
// check the avcC atom's sps for number of reference frames and
// bail if interlaced, VDA does not handle interlaced h264.
bool interlaced = true;
uint8_t *spc = extradata + 6;
uint32_t sps_size = AV_RB16(spc);
if (sps_size)
parseh264_sps(spc+3, sps_size-1, level, profile, &interlaced, max_ref_frames);
if (interlaced)
return false;
return true;
}
#endif
......@@ -27,3 +27,5 @@
IjkMediaPlayer *ijkmp_ios_create(int (*msg_loop)(void*));
void ijkmp_ios_set_glview(IjkMediaPlayer *mp, IJKSDLGLView *glView);
void ijkmp_ios_set_videotoolbox_enabled(IjkMediaPlayer *mp, BOOL enabled);
void ijkmp_ios_set_frame_max_width(IjkMediaPlayer *mp, int width);
......@@ -30,6 +30,7 @@
#include "ijkplayer/ff_ffplay.h"
#include "ijkplayer/ijkplayer_internal.h"
#include "ijkplayer/pipeline/ffpipeline_ffplay.h"
#include "ffpipeline_ios.h"
IjkMediaPlayer *ijkmp_ios_create(int (*msg_loop)(void*))
{
......@@ -45,7 +46,7 @@ IjkMediaPlayer *ijkmp_ios_create(int (*msg_loop)(void*))
if (!mp->ffplayer->vout)
goto fail;
mp->ffplayer->pipeline = ffpipeline_create_from_ffplay(mp->ffplayer);
mp->ffplayer->pipeline = ffpipeline_create_from_ios(mp->ffplayer);
if (!mp->ffplayer->pipeline)
goto fail;
......@@ -74,3 +75,43 @@ void ijkmp_ios_set_glview(IjkMediaPlayer *mp, IJKSDLGLView *glView)
pthread_mutex_unlock(&mp->mutex);
MPTRACE("ijkmp_ios_set_view(glView=%p)=void\n", (void*)glView);
}
void ijkmp_ios_set_frame_max_width_l(IjkMediaPlayer *mp, int width)
{
assert(mp);
assert(mp->ffplayer);
assert(mp->ffplayer->pipeline);
ffpipeline_ios_set_frame_max_width(mp->ffplayer->pipeline, width);
}
void ijkmp_ios_set_frame_max_width(IjkMediaPlayer *mp, int width)
{
assert(mp);
MPTRACE("%s (width=%d)\n", __func__, width);
pthread_mutex_lock(&mp->mutex);
ijkmp_ios_set_frame_max_width_l(mp, width);
pthread_mutex_unlock(&mp->mutex);
MPTRACE("%s after(width=%d)\n", __func__, width);
}
void ijkmp_ios_set_videotoolbox_enabled_l(IjkMediaPlayer *mp, BOOL enabled)
{
assert(mp);
assert(mp->ffplayer);
assert(mp->ffplayer->pipeline);
if (enabled == YES) {
ffpipeline_ios_set_videotoolbox_enabled(mp->ffplayer->pipeline, 1);
} else {
ffpipeline_ios_set_videotoolbox_enabled(mp->ffplayer->pipeline, 0);
}
}
void ijkmp_ios_set_videotoolbox_enabled(IjkMediaPlayer *mp, BOOL enabled)
{
assert(mp);
MPTRACE("%s enable(EnableFlag=%d)\n", __func__, enabled);
pthread_mutex_lock(&mp->mutex);
ijkmp_ios_set_videotoolbox_enabled_l(mp, enabled);
pthread_mutex_unlock(&mp->mutex);
MPTRACE("%s enable(EnableFlag=%d)\n", __func__, enabled);
}
/*****************************************************************************
* IJKVideoToolBox.h
*****************************************************************************
*
* copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef IJKMediaPlayer_videotoolbox_core_h
#define IJKMediaPlayer_videotoolbox_core_h
#import <VideoToolbox/VideoToolbox.h>
#include "ff_ffinc.h"
#include "ff_fferror.h"
#include "ff_ffmsg.h"
#include "ff_ffplay.h"
typedef struct VTBPicture {
double pts;
double dts;
double sort;
CVPixelBufferRef cvBufferRef;
uint64_t width;
uint64_t height;
} VTBPicture;
typedef struct sort_queue {
double dts;
double pts;
double sort;
int64_t width;
int64_t height;
CVPixelBufferRef pixel_buffer_ref;
volatile struct sort_queue *nextframe;
} sort_queue;
typedef struct VideoToolBoxContext {
FFPlayer *ffp;
AVCodecContext video_dec_ctx;
int width;
int height;
volatile bool refresh_request;
VTDecompressionSessionRef m_vt_session;
CMFormatDescriptionRef m_fmt_desc;
const char *m_pformat_name;
VTBPicture m_videobuffer;
double m_sort_time_offset;
pthread_mutex_t m_queue_mutex;
volatile sort_queue *m_sort_queue;
volatile int32_t m_queue_depth;
int32_t m_max_ref_frames;
bool m_convert_bytestream;
bool m_convert_3byteTo4byteNALSize;
} VideoToolBoxContext ;
VideoToolBoxContext* init_videotoolbox(FFPlayer* ffp, AVCodecContext* ic);
int videotoolbox_decode_video(VideoToolBoxContext* context, AVCodecContext *avctx, const AVPacket *avpkt,int* got_picture_ptr);
void dealloc_videotoolbox(VideoToolBoxContext* context);
#endif
/*
* ffpipeline_ios.c
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ffpipeline_ios.h"
#include "ffpipenode_ios_videotoolbox_vdec.h"
#include "ffpipenode_ios_videotoolbox_vout.h"
#include "ffpipenode_ffplay_vdec.h"
#include "ff_ffplay.h"
typedef struct IJKFF_Pipeline_Opaque {
FFPlayer *ffp;
int m_max_frame_width;
int m_videotoolbox_enable;
} IJKFF_Pipeline_Opaque;
static void func_destroy(IJKFF_Pipeline *pipeline)
{
}
void ffpipeline_ios_set_frame_max_width(IJKFF_Pipeline *pipeline, int max_frame_width)
{
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
opaque->m_max_frame_width = max_frame_width;
}
int ffpipeline_ios_get_frame_max_width(IJKFF_Pipeline *pipeline)
{
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
return opaque->m_max_frame_width;
}
void ffpipeline_ios_set_videotoolbox_enabled(IJKFF_Pipeline *pipeline, int enabled)
{
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
opaque->m_videotoolbox_enable = enabled;
}
static IJKFF_Pipenode *func_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
IJKFF_Pipenode* node = NULL;
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
if (opaque->m_videotoolbox_enable) {
node = ffpipenode_create_video_decoder_from_ios_videotoolbox(ffp);
}
if (node == NULL) {
ALOGE("vtb fail!!! switch to ffmpeg decode!!!! \n");
node = ffpipenode_create_video_decoder_from_ffplay(ffp);
}
return node;
}
static IJKFF_Pipenode *func_open_video_output(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
return ffpipenode_create_video_output_from_ios_videotoolbox(ffp);
}
static SDL_Class g_pipeline_class = {
.name = "ffpipeline_ios",
};
IJKFF_Pipeline *ffpipeline_create_from_ios(FFPlayer *ffp)
{
IJKFF_Pipeline *pipeline = ffpipeline_alloc(&g_pipeline_class, sizeof(IJKFF_Pipeline_Opaque));
if (!pipeline)
return pipeline;
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
opaque->ffp = ffp;
opaque->m_max_frame_width = 0;
opaque->m_videotoolbox_enable = 0;
pipeline->func_destroy = func_destroy;
pipeline->func_open_video_decoder = func_open_video_decoder;
pipeline->func_open_video_output = func_open_video_output;
return pipeline;
fail:
ffpipeline_free_p(&pipeline);
return NULL;
}
/*
* ffpipeline_ios.h
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFPLAY__FF_FFPIPELINE_IOS_H
#define FFPLAY__FF_FFPIPELINE_IOS_H
#include "ijkplayer/ff_ffpipeline.h"
typedef struct FFPlayer FFPlayer;
typedef struct IJKFF_Pipeline IJKFF_Pipeline;
IJKFF_Pipeline *ffpipeline_create_from_ios(FFPlayer *ffp);
void ffpipeline_ios_set_frame_max_width(IJKFF_Pipeline *pipeline, int width);
int ffpipeline_ios_get_frame_max_width(IJKFF_Pipeline *pipeline);
void ffpipeline_ios_set_videotoolbox_enabled(IJKFF_Pipeline *pipeline, int enabled);
#endif
/*
* ffpipenode_ios_videotoolbox_vdec.h
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFPLAY__FF_FFPIPENODE_IOS_VIDEOTOOLBOX_DEC_H
#define FFPLAY__FF_FFPIPENODE_IOS_VIDEOTOOLBOX_DEC_H
#include "ijkplayer/ff_ffpipenode.h"
typedef struct FFPlayer FFPlayer;
IJKFF_Pipenode *ffpipenode_create_video_decoder_from_ios_videotoolbox(FFPlayer *ffp);
#endif
/*
* ffpipenode_ios_videotoolbox_vdec.m
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ffpipenode_ios_videotoolbox_vdec.h"
#include "IJKVideoToolBox.h"
#include "ijksdl_vout_overlay_videotoolbox.h"
#include "ijkplayer/ff_ffpipeline.h"
#include "ijkplayer/ff_ffpipenode.h"
#include "ijkplayer/ff_ffplay.h"
#include "ijksdl_mutex.h"
#include "ijksdl_vout_ios_gles2.h"
typedef struct IJKFF_Pipenode_Opaque {
IJKFF_Pipeline *pipeline;
FFPlayer *ffp;
Decoder *decoder;
VideoToolBoxContext *context;
AVCodecContext *avctx; // not own
SDL_Thread* video_fill_thread;
SDL_Thread _video_fill_thread;
} IJKFF_Pipenode_Opaque;
int decoder_decode_frame_videotoolbox(VideoToolBoxContext* context) {
FFPlayer *ffp = context->ffp;
VideoState *is = ffp->is;
Decoder *d = &is->viddec;
int got_frame = 0;
do {
int ret = -1;
if (is->abort_request || d->queue->abort_request) {
return -1;
}
if (!d->packet_pending || d->queue->serial != d->pkt_serial) {
AVPacket pkt;
do {
if (d->queue->nb_packets == 0)
SDL_CondSignal(d->empty_queue_cond);
if (ffp_packet_queue_get_or_buffering(ffp, d->queue, &pkt, &d->pkt_serial, &d->finished) < 0)
return -1;
if (ffp_is_flush_packet(&pkt)) {
avcodec_flush_buffers(d->avctx);
context->refresh_request = true;
d->finished = 0;
d->next_pts = d->start_pts;
d->next_pts_tb = d->start_pts_tb;
}
} while (ffp_is_flush_packet(&pkt) || d->queue->serial != d->pkt_serial);
av_free_packet(&d->pkt);
d->pkt_temp = d->pkt = pkt;
d->packet_pending = 1;
}
ret = videotoolbox_decode_video(context, d->avctx, &d->pkt_temp, &got_frame);
if (ret < 0) {
d->packet_pending = 0;
} else {
d->pkt_temp.dts =
d->pkt_temp.pts = AV_NOPTS_VALUE;
if (d->pkt_temp.data) {
if (d->avctx->codec_type != AVMEDIA_TYPE_AUDIO)
ret = d->pkt_temp.size;
d->pkt_temp.data += ret;
d->pkt_temp.size -= ret;
if (d->pkt_temp.size <= 0)
d->packet_pending = 0;
} else {
if (!got_frame) {
d->packet_pending = 0;
d->finished = d->pkt_serial;
}
}
}
} while (!got_frame && !d->finished);
return got_frame;
}
int videotoolbox_video_thread(void *arg)
{
IJKFF_Pipenode_Opaque* opaque = (IJKFF_Pipenode_Opaque*) arg;
FFPlayer *ffp = opaque->ffp;
VideoState *is = ffp->is;
Decoder *d = &is->viddec;
int ret = 0;
opaque->context->ffp = ffp;
for (;;) {
if (is->abort_request || d->queue->abort_request) {
return -1;
}
@autoreleasepool {
ret = decoder_decode_frame_videotoolbox(opaque->context);
}
if (ret < 0)
goto the_end;
if (!ret)
continue;
if (ret < 0)
goto the_end;
}
the_end:
return 0;
}
static void func_destroy(IJKFF_Pipenode *node)
{
ALOGI("pipeline!!! destory!!!!!\n %d", (int)node);
if (!node || !node->opaque)
return;
IJKFF_Pipenode_Opaque *opaque = node->opaque;
if (opaque->context) {
dealloc_videotoolbox(opaque->context);
}
}
static int func_run_sync(IJKFF_Pipenode *node)
{
IJKFF_Pipenode_Opaque *opaque = node->opaque;
return videotoolbox_video_thread(opaque);
}
IJKFF_Pipenode *ffpipenode_create_video_decoder_from_ios_videotoolbox(FFPlayer *ffp)
{
if (!ffp || !ffp->is)
return NULL;
IJKFF_Pipenode *node = ffpipenode_alloc(sizeof(IJKFF_Pipenode_Opaque));
if (!node)
return node;
memset(node, sizeof(IJKFF_Pipenode), 0);
VideoState *is = ffp->is;
IJKFF_Pipenode_Opaque *opaque = node->opaque;
node->func_destroy = func_destroy;
node->func_run_sync = func_run_sync;
opaque->ffp = ffp;
opaque->decoder = &is->viddec;
opaque->avctx = opaque->decoder->avctx;
switch (opaque->avctx->codec_id) {
case AV_CODEC_ID_H264:
opaque->context = init_videotoolbox(ffp, opaque->avctx);
break;
default:
ALOGI("Videotoolbox-pipeline:open_video_decoder: not H264\n");
goto fail;
}
if (opaque->context == NULL) {
ALOGE("could not init video tool box decoder !!!");
goto fail;
}
return node;
fail:
ffpipenode_free_p(&node);
return NULL;
}
/*
* ffpipenode_ios_videotoolbox_vout.h
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFPLAY__FF_FFPIPENODE_IOS_VIDEOTOOLBOX_VOUT_H
#define FFPLAY__FF_FFPIPENODE_IOS_VIDEOTOOLBOX_VOUT_H
#include "ijkplayer/ff_ffpipenode.h"
typedef struct FFPlayer FFPlayer;
IJKFF_Pipenode *ffpipenode_create_video_output_from_ios_videotoolbox(FFPlayer *ffp);
#endif
/*
* ffpipenode_ios_videotoolbox_vout.m
*
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ffpipenode_ios_videotoolbox_vout.h"
#include "ff_ffpipeline.h"
#include "IJKVideoToolBox.h"
#include "ijkplayer/ff_ffpipenode.h"
#include "ijkplayer/ff_ffplay.h"
typedef struct IJKFF_Pipenode_Opaque {
FFPlayer *ffp;
} IJKFF_Pipenode_Opaque;
static void func_destroy(IJKFF_Pipenode *node)
{
// do nothing
}
static int func_run_sync(IJKFF_Pipenode *node)
{
IJKFF_Pipenode_Opaque *opaque = node->opaque;
int ret = ffp_video_refresh_thread(opaque->ffp);
return ret;
}
IJKFF_Pipenode *ffpipenode_create_video_output_from_ios_videotoolbox(FFPlayer *ffp)
{
IJKFF_Pipenode *node = ffpipenode_alloc(sizeof(IJKFF_Pipenode_Opaque));
if (!node)
return node;
IJKFF_Pipenode_Opaque *opaque = node->opaque;
opaque->ffp = ffp;
node->func_destroy = func_destroy;
node->func_run_sync = func_run_sync;
return node;
}
/*
* IJKSDLGLRenderNV12.h
*
* Copyright (c) 2014 Zhang Rui <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
......
/*
* IJKSDLGLRenderNV12.m
*
* Copyright (c) 2014 Zhou Quan <bbcallen@gmail.com>
*
* based on https://github.com/kolyvan/kxmovie
* Copyright (c) 2014 Zhou Quan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
......@@ -55,9 +53,9 @@ static NSString *const g_nv12FragmentShaderString = IJK_SHADER_STRING
// BT.709, which is the standard for HDTV.
static const GLfloat kColorConversion709[] = {
1.164, 1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533, 0.0,
1.164, 1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533, 0.0,
};
......@@ -93,6 +91,11 @@ static const GLfloat kColorConversion709[] = {
assert(overlay->format == SDL_FCC_NV12);
assert(overlay->planes == 2);
if (overlay->pixels[0] == NULL || overlay->pixels[1] == NULL)
{
return;
}
const NSUInteger frameHeight = overlay->h;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
......
......@@ -28,6 +28,8 @@
#include "ijksdl/ijksdl_vout_internal.h"
#include "ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.h"
#import "IJKSDLGLView.h"
#include "ijksdl_vout_overlay_videotoolbox.h"
#import "IJKVideoToolBox.h"
typedef struct SDL_VoutSurface_Opaque {
SDL_Vout *vout;
......@@ -39,7 +41,14 @@ typedef struct SDL_Vout_Opaque {
static SDL_VoutOverlay *vout_create_overlay_l(int width, int height, Uint32 format, SDL_Vout *vout)
{
return SDL_VoutFFmpeg_CreateOverlay(width, height, format, vout);
if (format == SDL_FCC_NV12)
{
return SDL_VoutVideoToolBox_CreateOverlay(width, height, format, vout);
}
else
{
return SDL_VoutFFmpeg_CreateOverlay(width, height, format, vout);
}
}
static SDL_VoutOverlay *vout_create_overlay(int width, int height, Uint32 format, SDL_Vout *vout)
......@@ -109,7 +118,6 @@ SDL_Vout *SDL_VoutIos_CreateForGLES2()
SDL_Vout_Opaque *opaque = vout->opaque;
opaque->gl_view = nil;
vout->create_overlay = vout_create_overlay;
vout->free_l = vout_free_l;
vout->display_overlay = voud_display_overlay;
......
/*****************************************************************************
* ijksdl_vout_overlay_videotoolbox.h
*****************************************************************************
*
* copyright (c) 2014 ZhouQuan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __IJKMediaPlayer__ijksdl_vout_overlay_videotoolbox__
#define __IJKMediaPlayer__ijksdl_vout_overlay_videotoolbox__
#include "ijksdl_stdinc.h"
#include "ijksdl_vout.h"
#include "IJKVideoToolBox.h"
#include "ijksdl_inc_ffmpeg.h"
SDL_VoutOverlay *SDL_VoutVideoToolBox_CreateOverlay(int width, int height, Uint32 format, SDL_Vout *vout);
int SDL_VoutOverlayVideoToolBox_FillFrame(SDL_VoutOverlay *overlay, VTBPicture* picture);
#endif
/*****************************************************************************
* ijksdl_vout_overlay_videotoolbox.m
*****************************************************************************
*
* copyright (c) 2014 ZhouQuan <zhouqicy@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ijksdl_vout_overlay_videotoolbox.h"
#include <assert.h>
#include "ijksdl_stdinc.h"
#include "ijksdl_mutex.h"
#include "ijksdl_vout_internal.h"
#include "ijksdl_video.h"
#include "IJKVideoToolBox.h"
typedef struct SDL_VoutOverlay_Opaque {
SDL_mutex *mutex;
CVBufferRef pixBuffer;
Uint16 pitches[AV_NUM_DATA_POINTERS];
Uint8 *pixels[AV_NUM_DATA_POINTERS];
} SDL_VoutOverlay_Opaque;
static void overlay_free_l(SDL_VoutOverlay *overlay)
{
if (!overlay)
return;
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
if (!opaque)
return;
overlay->unref(overlay);
if (opaque->mutex)
SDL_DestroyMutex(opaque->mutex);
SDL_VoutOverlay_FreeInternal(overlay);
}
int SDL_VoutOverlayVideoToolBox_FillFrame(SDL_VoutOverlay *overlay, VTBPicture* picture)
{
CVBufferRef pixBuffer = CVBufferRetain(picture->cvBufferRef);
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
if (opaque->pixBuffer != NULL) {
CVBufferRelease(opaque->pixBuffer);
}
opaque->pixBuffer = pixBuffer;
overlay->format = SDL_FCC_NV12;
overlay->planes = 2;
if (CVPixelBufferLockBaseAddress(pixBuffer, 0) != kCVReturnSuccess) {
overlay->pixels[0] = NULL;
overlay->pixels[1] = NULL;
overlay->pitches[0] = 0;
overlay->pitches[1] = 0;
overlay->w = 0;
overlay->h = 0;
CVBufferRelease(pixBuffer);
opaque->pixBuffer = NULL;
return -1;
}
overlay->pixels[0] = CVPixelBufferGetBaseAddressOfPlane(pixBuffer, 0);
overlay->pixels[1] = CVPixelBufferGetBaseAddressOfPlane(pixBuffer, 1);
overlay->pitches[0] = CVPixelBufferGetBytesPerRowOfPlane(pixBuffer, 0);
overlay->pitches[1] = CVPixelBufferGetBytesPerRowOfPlane(pixBuffer, 1);
overlay->w = (int)picture->width;
overlay->h = (int)picture->height;
CVPixelBufferUnlockBaseAddress(pixBuffer, 0);
return 0;
}
static int overlay_lock(SDL_VoutOverlay *overlay)
{
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
return SDL_LockMutex(opaque->mutex);
}
static int overlay_unlock(SDL_VoutOverlay *overlay)
{
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
return SDL_UnlockMutex(opaque->mutex);
}
static void overlay_unref(SDL_VoutOverlay *overlay)
{
if (!overlay) {
return;
}
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
if (!opaque) {
return;
}
CVBufferRelease(opaque->pixBuffer);
opaque->pixBuffer = NULL;
overlay->pixels[0] = NULL;
overlay->pixels[1] = NULL;
return;
}
SDL_VoutOverlay *SDL_VoutVideoToolBox_CreateOverlay(int width, int height, Uint32 format, SDL_Vout *display)
{
SDLTRACE("SDL_VoutVideoToolBox_CreateOverlay(w=%d, h=%d, fmt=%.4s(0x%x, dp=%p)\n", width, height, (const char*) &format, format, display);
SDL_VoutOverlay *overlay = SDL_VoutOverlay_CreateInternal(sizeof(SDL_VoutOverlay_Opaque));
if (!overlay) {
ALOGE("overlay allocation failed");
return NULL;
}
SDL_VoutOverlay_Opaque *opaque = overlay->opaque;
overlay->format = format;
overlay->w = width;
overlay->h = height;
overlay->pitches = opaque->pitches;
overlay->pixels = opaque->pixels;
overlay->free_l = overlay_free_l;
overlay->lock = overlay_lock;
overlay->unlock = overlay_unlock;
overlay->unref = overlay_unref;
opaque->mutex = SDL_CreateMutex();
return overlay;
fail:
overlay_free_l(overlay);
return NULL;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册