From 08bdc5e0cec3e2830b1fa7680023875a6ad06eeb Mon Sep 17 00:00:00 2001 From: befovy Date: Sat, 11 Jul 2020 15:24:42 +0800 Subject: [PATCH 01/11] fix: flush audio before toggle eof fixes https://github.com/befovy/fijkplayer/issues/275 --- ijkmedia/ijkplayer/ff_ffplay.c | 1 + .../IJKMediaDemo.xcodeproj/project.pbxproj | 51 +++++++------------ .../IJKMediaDemo/IJKMediaControl.m | 3 +- .../IJKMoviePlayerViewController.h | 2 +- .../IJKMediaPlayer.xcodeproj/project.pbxproj | 2 +- 5 files changed, 23 insertions(+), 36 deletions(-) diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index a2c4668a6d..8bde6c1bfd 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -3551,6 +3551,7 @@ static int read_thread(void *arg) // TODO: 0 it's a bit early to notify complete here ffp_toggle_buffering(ffp, 0); + SDL_AoutFlushAudio(ffp->aout); toggle_pause(ffp, 1); if (ffp->error) { av_log(ffp, AV_LOG_INFO, "ffp_toggle_buffering: error: %d\n", ffp->error); diff --git a/ios/IJKMediaDemo/IJKMediaDemo.xcodeproj/project.pbxproj b/ios/IJKMediaDemo/IJKMediaDemo.xcodeproj/project.pbxproj index 9073ab1139..b9d87ea3bc 100644 --- a/ios/IJKMediaDemo/IJKMediaDemo.xcodeproj/project.pbxproj +++ b/ios/IJKMediaDemo/IJKMediaDemo.xcodeproj/project.pbxproj @@ -7,9 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 21B5D5B322D8A6CC00A1D26D /* IJKMediaFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E654EAD71B6B28B100B0F2D0 /* IJKMediaFramework.framework */; }; - 21B5D5B822D8A6EA00A1D26D /* IJKMediaFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E654EAD71B6B28B100B0F2D0 /* IJKMediaFramework.framework */; }; - 21B5D5B922D8A6EA00A1D26D /* IJKMediaFramework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E654EAD71B6B28B100B0F2D0 /* IJKMediaFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 45D57D611A53233200BDD389 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45D57D601A53233200BDD389 /* CoreVideo.framework */; }; 45D57D631A53233800BDD389 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45D57D621A53233800BDD389 /* VideoToolbox.framework */; }; 546736C41E2371AE00FEE0DF /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 546736C31E2371AE00FEE0DF /* libstdc++.tbd */; }; @@ -49,6 +46,8 @@ E6F1D4C01D38F29D00E8665B /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F1D4BF1D38F29D00E8665B /* libbz2.tbd */; }; E6F524EB1B183A0700B69DC7 /* IJKDemoSampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6F524E91B183A0700B69DC7 /* IJKDemoSampleViewController.m */; }; E6F524EC1B183A0700B69DC7 /* IJKDemoSampleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E6F524EA1B183A0700B69DC7 /* IJKDemoSampleViewController.xib */; }; + F3E8249224B0C80100F2B1C5 /* IJKMediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21B5D5B222D8A5E500A1D26D /* IJKMediaPlayer.framework */; }; + F3E8249324B0C86700F2B1C5 /* IJKMediaPlayer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21B5D5B222D8A5E500A1D26D /* IJKMediaPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -66,20 +65,6 @@ remoteGlobalIDString = 21E6F50322C39D0500611D3D; remoteInfo = FIJKPlayer; }; - 21B5D5B522D8A6CC00A1D26D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E6D74F2918A5F94B00165BFD /* IJKMediaPlayer.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E654EA891B6B27E600B0F2D0; - remoteInfo = IJKMediaFramework; - }; - 21B5D5BA22D8A6EA00A1D26D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E6D74F2918A5F94B00165BFD /* IJKMediaPlayer.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E654EA891B6B27E600B0F2D0; - remoteInfo = IJKMediaFramework; - }; E654EAD61B6B28B100B0F2D0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E6D74F2918A5F94B00165BFD /* IJKMediaPlayer.xcodeproj */; @@ -94,6 +79,13 @@ remoteGlobalIDString = E654EA941B6B27E600B0F2D0; remoteInfo = IJKMediaFrameworkTests; }; + F3E8248D24B0C7F300F2B1C5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E6D74F2918A5F94B00165BFD /* IJKMediaPlayer.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 21E6F47922C39D0500611D3D; + remoteInfo = IJKMediaPlayer; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -103,7 +95,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 21B5D5B922D8A6EA00A1D26D /* IJKMediaFramework.framework in Embed Frameworks */, + F3E8249324B0C86700F2B1C5 /* IJKMediaPlayer.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -171,11 +163,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F3E8249224B0C80100F2B1C5 /* IJKMediaPlayer.framework in Frameworks */, 546736C41E2371AE00FEE0DF /* libstdc++.tbd in Frameworks */, E63FC29117F04C83003551EB /* AudioToolbox.framework in Frameworks */, E61B45AE19EF7021002792EC /* AVFoundation.framework in Frameworks */, - 21B5D5B822D8A6EA00A1D26D /* IJKMediaFramework.framework in Frameworks */, - 21B5D5B322D8A6CC00A1D26D /* IJKMediaFramework.framework in Frameworks */, E64D4F4E1938CCCC00F1C75D /* CoreGraphics.framework in Frameworks */, E60E8C2A19EF70BB005B5B6E /* CoreMedia.framework in Frameworks */, 45D57D611A53233200BDD389 /* CoreVideo.framework in Frameworks */, @@ -314,7 +305,7 @@ E654EAD71B6B28B100B0F2D0 /* IJKMediaFramework.framework */, 21B5D5B022D8A5E500A1D26D /* IJKMediaFrameworkWithSSL.framework */, E654EAD91B6B28B100B0F2D0 /* IJKMediaFrameworkTests.xctest */, - 21B5D5B222D8A5E500A1D26D /* IJKPlayer.framework */, + 21B5D5B222D8A5E500A1D26D /* IJKMediaPlayer.framework */, ); name = Products; sourceTree = ""; @@ -334,8 +325,7 @@ buildRules = ( ); dependencies = ( - 21B5D5B622D8A6CC00A1D26D /* PBXTargetDependency */, - 21B5D5BB22D8A6EA00A1D26D /* PBXTargetDependency */, + F3E8248E24B0C7F300F2B1C5 /* PBXTargetDependency */, ); name = IJKMediaDemo; productName = IJKMediaDemo; @@ -389,10 +379,10 @@ remoteRef = 21B5D5AF22D8A5E500A1D26D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 21B5D5B222D8A5E500A1D26D /* IJKPlayer.framework */ = { + 21B5D5B222D8A5E500A1D26D /* IJKMediaPlayer.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; - path = IJKPlayer.framework; + path = IJKMediaPlayer.framework; remoteRef = 21B5D5B122D8A5E500A1D26D /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -458,15 +448,10 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 21B5D5B622D8A6CC00A1D26D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = IJKMediaFramework; - targetProxy = 21B5D5B522D8A6CC00A1D26D /* PBXContainerItemProxy */; - }; - 21B5D5BB22D8A6EA00A1D26D /* PBXTargetDependency */ = { + F3E8248E24B0C7F300F2B1C5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = IJKMediaFramework; - targetProxy = 21B5D5BA22D8A6EA00A1D26D /* PBXContainerItemProxy */; + name = IJKMediaPlayer; + targetProxy = F3E8248D24B0C7F300F2B1C5 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ diff --git a/ios/IJKMediaDemo/IJKMediaDemo/IJKMediaControl.m b/ios/IJKMediaDemo/IJKMediaDemo/IJKMediaControl.m index 1104b69c08..40225e5c25 100644 --- a/ios/IJKMediaDemo/IJKMediaDemo/IJKMediaControl.m +++ b/ios/IJKMediaDemo/IJKMediaDemo/IJKMediaControl.m @@ -16,7 +16,8 @@ */ #import "IJKMediaControl.h" -#import +#import + @implementation IJKMediaControl { diff --git a/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.h b/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.h index 81e2e16442..a082a923bf 100644 --- a/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.h +++ b/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.h @@ -16,7 +16,7 @@ */ #import -#import +#import @class IJKMediaControl; @interface IJKVideoViewController : UIViewController diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj b/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj index eceb08fab5..e33f7aed9f 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj +++ b/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj @@ -1773,7 +1773,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CONFIGURATION_BUILD_DIR = "$(HOME)/Flutter/fijkplayer/ios/Frameworks"; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"; CURRENT_PROJECT_VERSION = 0.8.8; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; From fcfc5acb851e8abdee67aa8c8bb53666a9815abf Mon Sep 17 00:00:00 2001 From: befovy Date: Sat, 11 Jul 2020 15:38:05 +0800 Subject: [PATCH 02/11] chore: release 0.7.8 --- .github/workflows/ios_release.yml | 9 +++++++++ CHANGELOG.md | 5 +++++ android/ijkplayer/gradle.properties | 4 ++-- ios/CocoaPodsPub/BIJKPlayer.podspec | 6 +++--- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ios_release.yml b/.github/workflows/ios_release.yml index f250ef32a7..a6770d66b3 100644 --- a/.github/workflows/ios_release.yml +++ b/.github/workflows/ios_release.yml @@ -27,6 +27,15 @@ jobs: working-directory: ios/IJKMediaPlayer run: xcodebuild -project IJKMediaPlayer.xcodeproj -configuration Release -scheme Universal + + - name: Upload to Bintray + working-directory: ios/CocoaPodsPub + run: | + curl --progress-bar --verbose -T IJKMediaPlayer.tar.gz -ubefovy:${{ secrets.BINTRAY_APIKEY }} \ + -H "X-Bintray-Package:bijkplayer" \ + -H "X-Bintray-Version:${{ github.ref }}" \ + https://api.bintray.com/content/befovytray/bijkplayer/${{ github.ref }}/IJKMediaPlayer.tar.gz\;publish\=1 | tee /dev/null + - name: Create Release id: create_release uses: actions/create-release@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index b2f73a4a73..c2965cab42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. See [standa --- +## 0.7.8 (2020-07-11) + +* fix, flush audio before toggle eof + +--- ## 0.7.6 (2020-07-03) * fix: update position with duration value when playback complete ([f3d27d8](https://github.com/befovy/ijkplayer/commit/f3d27d832ba0a3472bb59c129c2c65591f8855d4)) diff --git a/android/ijkplayer/gradle.properties b/android/ijkplayer/gradle.properties index e25783be23..487193ceeb 100644 --- a/android/ijkplayer/gradle.properties +++ b/android/ijkplayer/gradle.properties @@ -17,8 +17,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME=0.7.6 -VERSION_CODE=000706 +VERSION_NAME=0.7.8 +VERSION_CODE=000708 GROUP=com.befovy.fijkplayer # http://central.sonatype.org/pages/requirements.html diff --git a/ios/CocoaPodsPub/BIJKPlayer.podspec b/ios/CocoaPodsPub/BIJKPlayer.podspec index 3546a219f7..3fe8581169 100644 --- a/ios/CocoaPodsPub/BIJKPlayer.podspec +++ b/ios/CocoaPodsPub/BIJKPlayer.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |spec| # spec.name = "BIJKPlayer" - spec.version = "0.7.6" + spec.version = "0.7.8" spec.summary = "ijkplayer iOS video player SDK" spec.author = { "befovy" => "befovy@gmail.com" } @@ -75,8 +75,8 @@ Pod::Spec.new do |spec| # Supports git, hg, bzr, svn and HTTP. # - spec.source = { :http => "https://github.com/befovy/ijkplayer/releases/download/f0.7.6/IJKMediaPlayer.tar.gz" } - + spec.source = { :http => "https://dl.bintray.com/befovytray/bijkplayer/f0.7.8/IJKMediaPlayer.tar.gz" } + # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # # CocoaPods is smart about how it includes source code. For source files From dafb3b37c148a06341a4971684bcb42300424ce8 Mon Sep 17 00:00:00 2001 From: befovy Date: Sat, 11 Jul 2020 16:29:09 +0800 Subject: [PATCH 03/11] ci: fix tag name, extract tag name --- .github/workflows/ios_release.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ios_release.yml b/.github/workflows/ios_release.yml index a6770d66b3..482f139030 100644 --- a/.github/workflows/ios_release.yml +++ b/.github/workflows/ios_release.yml @@ -28,13 +28,21 @@ jobs: run: xcodebuild -project IJKMediaPlayer.xcodeproj -configuration Release -scheme Universal + - name: Extract tag name + id: tag + uses: actions/github-script@0.2.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + return context.payload.ref.replace('refs/tags/', ''); + - name: Upload to Bintray working-directory: ios/CocoaPodsPub run: | curl --progress-bar --verbose -T IJKMediaPlayer.tar.gz -ubefovy:${{ secrets.BINTRAY_APIKEY }} \ -H "X-Bintray-Package:bijkplayer" \ - -H "X-Bintray-Version:${{ github.ref }}" \ - https://api.bintray.com/content/befovytray/bijkplayer/${{ github.ref }}/IJKMediaPlayer.tar.gz\;publish\=1 | tee /dev/null + -H "X-Bintray-Version:${{ steps.tag.outputs.result }}" \ + https://api.bintray.com/content/befovytray/bijkplayer/${{ steps.tag.outputs.result }}/IJKMediaPlayer.tar.gz\;publish\=1 | tee /dev/null - name: Create Release id: create_release From 24551445715301a08b3b802cac1f4e8415b65e39 Mon Sep 17 00:00:00 2001 From: befovy Date: Sat, 18 Jul 2020 14:14:27 +0800 Subject: [PATCH 04/11] android enable-protocol crypto --- android/contrib/tools/do-compile-ffmpeg.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/android/contrib/tools/do-compile-ffmpeg.sh b/android/contrib/tools/do-compile-ffmpeg.sh index 5bf8d17bd6..1822ac7978 100755 --- a/android/contrib/tools/do-compile-ffmpeg.sh +++ b/android/contrib/tools/do-compile-ffmpeg.sh @@ -287,6 +287,7 @@ if [ -f "${FF_DEP_OPENSSL_LIB}/libssl.a" ]; then echo "OpenSSL detected" # FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-nonfree" FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-openssl" + FF_CFG_FLAGS="$FF_CFG_FLAGS --enable-protocol=crypto" echo "${FF_DEP_OPENSSL_INC} ${FF_DEP_OPENSSL_LIB}" FF_CFLAGS="$FF_CFLAGS -I${FF_DEP_OPENSSL_INC}" FF_DEP_LIBS="$FF_DEP_LIBS -L${FF_DEP_OPENSSL_LIB} -lssl -lcrypto" From 2bd6be2d7a5c62c65faea026ede98b1a84829dad Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Wed, 28 Oct 2020 15:04:26 +0800 Subject: [PATCH 05/11] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=BD=95=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ijkmedia/ijkplayer/ff_ffplay.c | 242 ++++++++++++++++++ ijkmedia/ijkplayer/ff_ffplay.h | 4 + ijkmedia/ijkplayer/ff_ffplay_def.h | 9 + ijkmedia/ijkplayer/ijkplayer.c | 26 ++ ijkmedia/ijkplayer/ijkplayer.h | 3 + .../IJKMediaPlayer/IJKFFMediaPlayer.h | 3 + .../IJKMediaPlayer/IJKFFMediaPlayer.m | 10 + ios/IJKMediaPlayer/universal-framework.sh | 1 + 8 files changed, 298 insertions(+) diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index 8bde6c1bfd..9d5925a4d7 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -3679,6 +3679,13 @@ static int read_thread(void *arg) } } } + //录制流程 + if (ffp->is_record) { // 可以录制时,写入文件 + if (0 != ffp_record_file(ffp, pkt)) { + ffp->record_error = 1; + ffp_stop_record(ffp); + } + } } ret = 0; @@ -5168,6 +5175,241 @@ void ffp_set_property_int64(FFPlayer *ffp, int id, int64_t value) break; } } + +//开始录制函数:file_name是保存路径 +int ffp_start_record(FFPlayer *ffp, const char *file_name) +{ + assert(ffp); + + VideoState *is = ffp->is; + avcodec_register_all(); + ffp->m_ofmt_ctx = NULL; + ffp->m_ofmt = NULL; + ffp->is_record = 0; + ffp->record_error = 0; + + if (!file_name || !strlen(file_name)) { // 没有路径 + av_log(ffp, AV_LOG_ERROR, "filename is invalid\n"); + goto end; + } + + if (!is || !is->ic|| is->paused || is->abort_request) { // 没有上下文,或者上下文已经停止 + av_log(ffp, AV_LOG_ERROR, "is,is->ic,is->paused is invalid\n"); + goto end; + } + + if (ffp->is_record) { // 已经在录制 + av_log(ffp, AV_LOG_ERROR, "recording has started\n"); + goto end; + } + + AVOutputFormat *oformat = av_guess_format(NULL, file_name, NULL); + // 初始化一个用于输出的AVFormatContext结构体 + avformat_alloc_output_context2(&ffp->m_ofmt_ctx, oformat, NULL, file_name); + av_log(NULL, AV_LOG_INFO, "===== 初始化一个用于输出的AVFormatContext结构体 =====\n"); + if (!ffp->m_ofmt_ctx) { + av_log(ffp, AV_LOG_ERROR, "Could not create output context filename is %s\n", file_name); + goto end; + } + ffp->m_ofmt = ffp->m_ofmt_ctx->oformat; + + for (int i = 0; i < is->ic->nb_streams; i++) { + // 对照输入流创建输出流通道 + AVStream *out_stream; + AVStream *in_stream = is->ic->streams[i]; + AVCodecParameters *in_codecpar = in_stream->codecpar; + if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO && + in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO && + in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) { + continue; + } + + out_stream = avformat_new_stream(ffp->m_ofmt_ctx, NULL); + + if (!out_stream) { + av_log(ffp, AV_LOG_ERROR, "Failed allocating output stream\n"); + goto end; + } + + // 将输入视频/音频的参数拷贝至输出视频/音频的AVCodecContext结构体 + av_log(NULL, AV_LOG_INFO, "===== 将输入视频/音频的参数拷贝至输出视频/音频的AVCodecContext结构体 =====\n"); + if (avcodec_parameters_copy(out_stream->codecpar, in_codecpar) < 0) { + av_log(ffp, AV_LOG_ERROR, "Failed to copy codec parameters\n"); + av_log(NULL, AV_LOG_INFO, "===== 将输入视频/音频的参数拷贝至输出视频/音频的AVCodecContext结构体,拷贝失败 =====\n"); + goto end; + } + out_stream->codecpar->codec_tag = 0; + //视频流中经常缺少重要参数,会导致写文件头失败,特此在这里处理 + if(out_stream->codecpar->width<=0){ + out_stream->codecpar->width=1920; + } + if(out_stream->codecpar->height<=0){ + out_stream->codecpar->height=1080; + } + if (!out_stream->codecpar->block_align) + out_stream->codecpar->block_align = out_stream->codecpar->channels * + av_get_bits_per_sample(out_stream->codecpar->codec_id) >> 3; + if(out_stream->codecpar->sample_rate<=0) + out_stream->codecpar->sample_rate = 44100; + int ret = avcodec_copy_context(out_stream->codec, in_stream->codec); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to copy context from input to output stream codec context, error:%1", ret); + goto end; + } + if (ffp->m_ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) + out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; +// out_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + } + + av_dump_format(ffp->m_ofmt_ctx, 0, file_name, 1); + + // 打开输出文件 + if (!(ffp->m_ofmt->flags & AVFMT_NOFILE)) { + if (avio_open(&ffp->m_ofmt_ctx->pb, file_name, AVIO_FLAG_WRITE) < 0) { + av_log(ffp, AV_LOG_ERROR, "Could not open output file '%s'", file_name); + goto end; + } + } + + // 写视频文件头 + av_log(NULL, AV_LOG_INFO, "===== 写视频文件头 =====\n"); + int state = avformat_write_header(ffp->m_ofmt_ctx, NULL); + av_log(NULL, AV_LOG_INFO, "===== 写视频文件头 =====返回值:%d\n",state); + if (state < 0) { + av_log(NULL, AV_LOG_INFO, "===== 写视频文件头失败 =====\n"); + av_log(ffp, AV_LOG_ERROR, "Error occurred when opening output file\n"); + goto end; + } + ffp->is_first = 0; + ffp->is_record = 1; + ffp->record_error = 0; + av_log(NULL, AV_LOG_INFO, "===== 文件录制开启成功 =====\n"); + pthread_mutex_init(&ffp->record_mutex, NULL); + + return 0; +end: + ffp->record_error = 1; + return -1; +} + +//停止录播 +int ffp_stop_record(FFPlayer *ffp) +{ + pthread_mutex_lock(&ffp->record_mutex); + assert(ffp); + av_log(NULL, AV_LOG_INFO, "===== 文件录制结束流程 =====\n"); + if (ffp->is_record) { + ffp->is_record = 0; + + if (ffp->m_ofmt_ctx != NULL) { + av_log(NULL, AV_LOG_INFO, "===== 开始写文件尾部 =====\n"); + int errorCode = av_write_trailer(ffp->m_ofmt_ctx); + av_log(NULL, AV_LOG_INFO, "===== 写文件尾部返回:%d =====\n",errorCode); + if (ffp->m_ofmt_ctx && !(ffp->m_ofmt->flags & AVFMT_NOFILE)) { + av_log(NULL, AV_LOG_INFO, "===== 开始关闭文件 =====\n"); + avio_close(ffp->m_ofmt_ctx->pb); + } + avformat_free_context(ffp->m_ofmt_ctx); + ffp->m_ofmt_ctx = NULL; + ffp->is_first = 0; + av_log(NULL, AV_LOG_INFO, "===== 文件录制结束成功 =====\n"); + } + + av_log(ffp, AV_LOG_DEBUG, "stopRecord ok\n"); + } else { + av_log(ffp, AV_LOG_ERROR, "don't need stopRecord\n"); + } + pthread_mutex_unlock(&ffp->record_mutex); + pthread_mutex_destroy(&ffp->record_mutex); + return 0; +} + + +//保存文件 +int ffp_record_file(FFPlayer *ffp, AVPacket *packet) +{ + pthread_mutex_lock(&ffp->record_mutex); + assert(ffp); + VideoState *is = ffp->is; + int ret = 0; + AVStream *in_stream; + AVStream *out_stream; + + if (ffp->is_record) { + if (packet == NULL) { + ffp->record_error = 1; + av_log(ffp, AV_LOG_ERROR, "packet == NULL"); + pthread_mutex_unlock(&ffp->record_mutex); + return -1; + } + + AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket)); // 与看直播的 AVPacket分开,不然卡屏 + av_new_packet(pkt, 0); + if (0 == av_packet_ref(pkt, packet)) { + + + av_log(ffp, AV_LOG_INFO, "ffp->start_pts:%"PRId64"",ffp->start_pts); + av_log(ffp, AV_LOG_INFO, "ffp->start_dts:%"PRId64"",ffp->start_dts); + + av_log(ffp, AV_LOG_INFO, "ffp->is_first:%"PRId64"",ffp->is_first); + if (!ffp->is_first) { // 录制的第一帧,时间从0开始 + if(pkt->flags==AV_PKT_FLAG_KEY){ + //取到I帧开始写录制数据 + ffp->is_first = 1; + ffp->start_pts = pkt->pts; + ffp->start_dts = pkt->dts; + pkt->pts = 0; + pkt->dts = 0; + }else{ + ffp->is_first = 0; + ffp->start_pts = pkt->pts; + ffp->start_dts = pkt->dts; + pkt->pts = 0; + pkt->dts = 0; + av_packet_unref(pkt); + pthread_mutex_unlock(&ffp->record_mutex); + return 0; + } + + } else { // 之后的每一帧都要减去,点击开始录制时的值,这样的时间才是正确的 + pkt->pts = llabs(pkt->pts - ffp->start_pts); + pkt->dts = llabs(pkt->dts - ffp->start_dts); + } + + if(pkt->ptsdts) + pkt->dts = pkt->pts; + if(pkt->dtspts) + pkt->pts = pkt->dts; + in_stream = is->ic->streams[pkt->stream_index]; + out_stream = ffp->m_ofmt_ctx->streams[pkt->stream_index]; + + // 转换PTS/DTS + pkt->pts = av_rescale_q_rnd(pkt->pts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); + pkt->dts = av_rescale_q_rnd(pkt->dts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); + pkt->duration = av_rescale_q(pkt->duration, in_stream->time_base, out_stream->time_base); + + pkt->pos = -1; + + + av_log(ffp, AV_LOG_INFO, "inner pkt->pts:%"PRId64"\n",pkt->pts); + av_log(ffp, AV_LOG_INFO, "inner pkt->dts:%"PRId64"\n",pkt->dts); + av_log(ffp, AV_LOG_INFO, "inner pkt->duration:%"PRId64"\n",pkt->duration); + + + av_log(ffp, AV_LOG_INFO, "av_interleaved_write_frame\n"); + // 写入一个AVPacket到输出文件 + if ((ret = av_interleaved_write_frame(ffp->m_ofmt_ctx, pkt)) < 0) { + av_log(ffp, AV_LOG_ERROR, "Error muxing packet\n"); + } + av_packet_unref(pkt); + pthread_mutex_unlock(&ffp->record_mutex); + } else { + av_log(ffp, AV_LOG_ERROR, "av_packet_ref == NULL"); + } + } + pthread_mutex_unlock(&ffp->record_mutex); + return ret; +} IjkMediaMeta *ffp_get_meta_l(FFPlayer *ffp) { diff --git a/ijkmedia/ijkplayer/ff_ffplay.h b/ijkmedia/ijkplayer/ff_ffplay.h index 536c67c151..6e3770d345 100644 --- a/ijkmedia/ijkplayer/ff_ffplay.h +++ b/ijkmedia/ijkplayer/ff_ffplay.h @@ -116,6 +116,10 @@ float ffp_get_property_float(FFPlayer *ffp, int id, float default_value); void ffp_set_property_float(FFPlayer *ffp, int id, float value); int64_t ffp_get_property_int64(FFPlayer *ffp, int id, int64_t default_value); void ffp_set_property_int64(FFPlayer *ffp, int id, int64_t value); +//录制相关 +int ffp_start_record(FFPlayer *ffp, const char *file_name); +int ffp_stop_record(FFPlayer *ffp); +int ffp_record_file(FFPlayer *ffp, AVPacket *packet); // must be freed with free(); struct IjkMediaMeta *ffp_get_meta_l(FFPlayer *ffp); diff --git a/ijkmedia/ijkplayer/ff_ffplay_def.h b/ijkmedia/ijkplayer/ff_ffplay_def.h index 6f54f7f731..76b8202cab 100755 --- a/ijkmedia/ijkplayer/ff_ffplay_def.h +++ b/ijkmedia/ijkplayer/ff_ffplay_def.h @@ -567,6 +567,15 @@ typedef struct FFPlayer { AVDictionary *player_opts; AVDictionary *swr_opts; AVDictionary *swr_preset_opts; + AVFormatContext *m_ofmt_ctx; // 用于输出的AVFormatContext结构体 + AVOutputFormat *m_ofmt; + pthread_mutex_t record_mutex; // 锁 + int is_record; // 是否在录制 + int record_error; + + int is_first; // 是否第一帧数据 + int64_t start_pts; // 开始录制pts + int64_t start_dts; // 开始录制dts /* ffplay options specified by the user */ #ifdef FFP_MERGE diff --git a/ijkmedia/ijkplayer/ijkplayer.c b/ijkmedia/ijkplayer/ijkplayer.c index dd2a4a8df6..0482a94e25 100755 --- a/ijkmedia/ijkplayer/ijkplayer.c +++ b/ijkmedia/ijkplayer/ijkplayer.c @@ -844,3 +844,29 @@ int ijkmp_get_msg(IjkMediaPlayer *mp, AVMessage *msg, int block) return -1; } + +int ijkmp_start_record(IjkMediaPlayer *mp,const char *file_name) +{ + assert(mp); + printf("=====开始录制准备====="); + MPTRACE("ijkmp_startRecord()\n"); + pthread_mutex_lock(&mp->mutex); + int retval = ffp_start_record(mp->ffplayer,file_name); + printf("=====开始录制已调用=====\n"); + pthread_mutex_unlock(&mp->mutex); + MPTRACE("ijkmp_startRecord()=%d\n", retval); + return retval; +} + +int ijkmp_stop_record(IjkMediaPlayer *mp) +{ + assert(mp); + MPTRACE("ijkmp_stopRecord()\n"); + printf("=====结束录制准备=====\n"); + pthread_mutex_lock(&mp->mutex); + int retval = ffp_stop_record(mp->ffplayer); + printf("=====结束录制已调用=====\n"); + pthread_mutex_unlock(&mp->mutex); + MPTRACE("ijkmp_stopRecord()=%d\n", retval); + return retval; +} diff --git a/ijkmedia/ijkplayer/ijkplayer.h b/ijkmedia/ijkplayer/ijkplayer.h index 58cc8e6f1b..8dbc5d6302 100644 --- a/ijkmedia/ijkplayer/ijkplayer.h +++ b/ijkmedia/ijkplayer/ijkplayer.h @@ -215,6 +215,9 @@ void *ijkmp_get_weak_thiz(IjkMediaPlayer *mp); void *ijkmp_set_weak_thiz(IjkMediaPlayer *mp, void *weak_thiz); void ijkmp_take_snapshot(IjkMediaPlayer *mp); +//录制方法 +int ijkmp_start_record(IjkMediaPlayer *mp,const char *file_name); +int ijkmp_stop_record(IjkMediaPlayer *mp); /* return < 0 if aborted, 0 if no packet and > 0 if packet. */ /* need to call msg_free_res for freeing the resouce obtained in msg */ diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h index 75149d0346..1f2e76f0c0 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h +++ b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h @@ -108,6 +108,9 @@ typedef void(^OnSnapshotBlock) (UIImage* __nullable image , NSError* __nullable - (void) addIJKMPEventHandler:(id) handler; - (void) removeIJKMPEventHandler:(id) handler; +- (int) startRecordVideo:(NSString*)fileRealPath; +- (int) stopRecordVideo; + @end NS_ASSUME_NONNULL_END diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m index 31fb5415b0..7fbde9c3d1 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m +++ b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m @@ -498,4 +498,14 @@ - (void)audioSessionInterrupt:(NSNotification *)notification } } } + +//开始录制 +- (int) startRecordVideo:(NSString*)fileRealPath{ + return ijkmp_start_record(_nativeMediaPlayer, [fileRealPath UTF8String]); +} +//结束录制 +- (int) stopRecordVideo{ + NSLog(@"结束录制"); + return ijkmp_stop_record(_nativeMediaPlayer); +} @end diff --git a/ios/IJKMediaPlayer/universal-framework.sh b/ios/IJKMediaPlayer/universal-framework.sh index 94c838a3f4..0fa9207765 100755 --- a/ios/IJKMediaPlayer/universal-framework.sh +++ b/ios/IJKMediaPlayer/universal-framework.sh @@ -22,6 +22,7 @@ cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME fi # Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory +lipo -remove arm64 "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" -o "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}" # Step 5. Convenience step to copy the framework to the project's directory From 3a65ec76624fdb12e93ad3ceb8e0662383ee5d24 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Wed, 28 Oct 2020 17:42:25 +0800 Subject: [PATCH 06/11] =?UTF-8?q?Android=E6=B7=BB=E5=8A=A0=E5=BD=95?= =?UTF-8?q?=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/widget/media/IjkVideoView.java | 7 +++++ .../ijk/media/player/IMediaPlayer.java | 3 +- .../ijk/media/player/IjkMediaPlayer.java | 8 +++++ .../ijk/media/player/MediaPlayerProxy.java | 6 ++++ ijkmedia/ijkplayer/android/ijkplayer_jni.c | 30 +++++++++++++++++++ 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java index fe1a49a9f7..ebaef3799a 100755 --- a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java +++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java @@ -150,6 +150,13 @@ public IjkVideoView(Context context, AttributeSet attrs, int defStyleAttr, int d initVideoView(context); } + public int startRecord(String recordVideoPath) { + return mMediaPlayer.startRecord(recordVideoPath); + } + + public int stopRecord() { + return mMediaPlayer.stopRecord(); + } // REMOVED: onMeasure // REMOVED: onInitializeAccessibilityEvent // REMOVED: onInitializeAccessibilityNodeInfo diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java index 730f3c0c5f..bf9f575244 100644 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java @@ -120,7 +120,8 @@ void setDataSource(String path) int getAudioSessionId(); MediaInfo getMediaInfo(); - + int startRecord(String recordVideoPath)throws IllegalStateException;; + int stopRecord()throws IllegalStateException; @SuppressWarnings("EmptyMethod") @Deprecated void setLogEnabled(boolean enable); diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java index 290a696f43..d26f6447e2 100755 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java @@ -634,6 +634,8 @@ public void setScreenOnWhilePlaying(boolean screenOn) { } } + + @SuppressLint("Wakelock") private void stayAwake(boolean awake) { if (mWakeLock != null) { @@ -972,6 +974,12 @@ public MediaInfo getMediaInfo() { return mediaInfo; } + @Override + public native int startRecord(String recordVideoPath)throws IllegalStateException; + + @Override + public native int stopRecord()throws IllegalStateException; + @Override public void setLogEnabled(boolean enable) { // do nothing diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java index 918cd0a16d..3d75ab4860 100644 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java @@ -357,4 +357,10 @@ public void setLooping(boolean looping) { public boolean isLooping() { return mBackEndMediaPlayer.isLooping(); } + + @Override + public native int startRecord(String recordVideoPath)throws IllegalStateException; + + @Override + public native int stopRecord()throws IllegalStateException; } diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c index a980a641ad..6f7338b74e 100755 --- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c +++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c @@ -418,6 +418,34 @@ IjkMediaPlayer_reset(JNIEnv *env, jobject thiz) ijkmp_dec_ref_p(&mp); } +//开始录屏 +static jint +IjkMediaPlayer_startRecord(JNIEnv *env, jclass thiz,jstring file) +{ + jint retval = 0; + IjkMediaPlayer *mp = jni_get_media_player(env, thiz); + JNI_CHECK_GOTO(mp, env, NULL, "mpjni: startRecord: null mp", LABEL_RETURN); + const char *nativeString = (*env)->GetStringUTFChars(env, file, 0); + retval = ijkmp_start_record(mp,nativeString); + +LABEL_RETURN: + ijkmp_dec_ref_p(&mp); + return retval; +} +//结束录屏 +static jint +IjkMediaPlayer_stopRecord(JNIEnv *env, jclass thiz) +{ + jint retval = 0; + IjkMediaPlayer *mp = jni_get_media_player(env, thiz); + JNI_CHECK_GOTO(mp, env, NULL, "mpjni: stopRecord: null mp", LABEL_RETURN); + + retval = ijkmp_stop_record(mp); + +LABEL_RETURN: + ijkmp_dec_ref_p(&mp); + return retval; +} static void IjkMediaPlayer_setLoopCount(JNIEnv *env, jobject thiz, jint loop_count) @@ -1249,6 +1277,8 @@ static JNINativeMethod g_methods[] = { { "native_setLogLevel", "(I)V", (void *) IjkMediaPlayer_native_setLogLevel }, { "_setFrameAtTime", "(Ljava/lang/String;JJII)V", (void *) IjkMediaPlayer_setFrameAtTime }, + { "startRecord", "(Ljava/lang/String;)I", (void *) IjkMediaPlayer_startRecord }, + { "stopRecord", "()V", (void *) IjkMediaPlayer_stopRecord }, }; JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) From 33fb8d7125b6d146e90a32a7e6bf3a08e068d578 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Thu, 29 Oct 2020 09:54:26 +0800 Subject: [PATCH 07/11] =?UTF-8?q?=E5=BD=95=E5=88=B6=E8=A7=86=E9=A2=91Andro?= =?UTF-8?q?id=E7=BC=96=E8=AF=91=E5=87=BA=E9=94=99=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E8=A7=A3=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../media/example/widget/media/IjkVideoView.java | 8 -------- .../tv/danmaku/ijk/media/player/IMediaPlayer.java | 3 +-- .../tv/danmaku/ijk/media/player/IjkMediaPlayer.java | 13 ++++++++----- .../danmaku/ijk/media/player/MediaPlayerProxy.java | 5 ----- ijkmedia/ijkplayer/android/ijkplayer_jni.c | 8 ++++---- ijkmedia/ijkplayer/ff_ffplay.c | 4 ++-- 6 files changed, 15 insertions(+), 26 deletions(-) diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java index ebaef3799a..f253783fad 100755 --- a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java +++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java @@ -149,14 +149,6 @@ public IjkVideoView(Context context, AttributeSet attrs, int defStyleAttr, int d super(context, attrs, defStyleAttr, defStyleRes); initVideoView(context); } - - public int startRecord(String recordVideoPath) { - return mMediaPlayer.startRecord(recordVideoPath); - } - - public int stopRecord() { - return mMediaPlayer.stopRecord(); - } // REMOVED: onMeasure // REMOVED: onInitializeAccessibilityEvent // REMOVED: onInitializeAccessibilityNodeInfo diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java index bf9f575244..730f3c0c5f 100644 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java @@ -120,8 +120,7 @@ void setDataSource(String path) int getAudioSessionId(); MediaInfo getMediaInfo(); - int startRecord(String recordVideoPath)throws IllegalStateException;; - int stopRecord()throws IllegalStateException; + @SuppressWarnings("EmptyMethod") @Deprecated void setLogEnabled(boolean enable); diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java index d26f6447e2..986a5ccff5 100755 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java @@ -973,12 +973,15 @@ public MediaInfo getMediaInfo() { } return mediaInfo; } + public int startRecord(String recordVideoPath)throws IllegalStateException{ + return _startRecord(recordVideoPath); + } + public int stopRecord()throws IllegalStateException{ + return _stopRecord(); + } + private native int _startRecord(String recordVideoPath)throws IllegalStateException; - @Override - public native int startRecord(String recordVideoPath)throws IllegalStateException; - - @Override - public native int stopRecord()throws IllegalStateException; + private native int _stopRecord()throws IllegalStateException; @Override public void setLogEnabled(boolean enable) { diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java index 3d75ab4860..d48f79e139 100644 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java @@ -358,9 +358,4 @@ public boolean isLooping() { return mBackEndMediaPlayer.isLooping(); } - @Override - public native int startRecord(String recordVideoPath)throws IllegalStateException; - - @Override - public native int stopRecord()throws IllegalStateException; } diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c index 6f7338b74e..a42f3c2c68 100755 --- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c +++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c @@ -424,7 +424,7 @@ IjkMediaPlayer_startRecord(JNIEnv *env, jclass thiz,jstring file) { jint retval = 0; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); - JNI_CHECK_GOTO(mp, env, NULL, "mpjni: startRecord: null mp", LABEL_RETURN); + JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException","mpjni: startRecord: null mp", LABEL_RETURN); const char *nativeString = (*env)->GetStringUTFChars(env, file, 0); retval = ijkmp_start_record(mp,nativeString); @@ -438,7 +438,7 @@ IjkMediaPlayer_stopRecord(JNIEnv *env, jclass thiz) { jint retval = 0; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); - JNI_CHECK_GOTO(mp, env, NULL, "mpjni: stopRecord: null mp", LABEL_RETURN); + JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: stopRecord: null mp", LABEL_RETURN); retval = ijkmp_stop_record(mp); @@ -1277,8 +1277,8 @@ static JNINativeMethod g_methods[] = { { "native_setLogLevel", "(I)V", (void *) IjkMediaPlayer_native_setLogLevel }, { "_setFrameAtTime", "(Ljava/lang/String;JJII)V", (void *) IjkMediaPlayer_setFrameAtTime }, - { "startRecord", "(Ljava/lang/String;)I", (void *) IjkMediaPlayer_startRecord }, - { "stopRecord", "()V", (void *) IjkMediaPlayer_stopRecord }, + { "_startRecord", "(Ljava/lang/String;)I", (void *) IjkMediaPlayer_startRecord }, + { "_stopRecord", "()I", (void *) IjkMediaPlayer_stopRecord }, }; JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index 9d5925a4d7..af92b897ec 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -5253,7 +5253,7 @@ int ffp_start_record(FFPlayer *ffp, const char *file_name) out_stream->codecpar->sample_rate = 44100; int ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to copy context from input to output stream codec context, error:%1", ret); + av_log(NULL, AV_LOG_ERROR, "Failed to copy context from input to output stream codec context, error:%d", ret); goto end; } if (ffp->m_ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) @@ -5351,7 +5351,7 @@ int ffp_record_file(FFPlayer *ffp, AVPacket *packet) av_log(ffp, AV_LOG_INFO, "ffp->start_pts:%"PRId64"",ffp->start_pts); av_log(ffp, AV_LOG_INFO, "ffp->start_dts:%"PRId64"",ffp->start_dts); - av_log(ffp, AV_LOG_INFO, "ffp->is_first:%"PRId64"",ffp->is_first); + av_log(ffp, AV_LOG_INFO, "ffp->is_first:%d",ffp->is_first); if (!ffp->is_first) { // 录制的第一帧,时间从0开始 if(pkt->flags==AV_PKT_FLAG_KEY){ //取到I帧开始写录制数据 From 6cc43dd3a9372f16c61787943801970c7d71a5d1 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Fri, 30 Oct 2020 06:24:54 +0800 Subject: [PATCH 08/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BD=95=E5=B1=8Fjni?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ijk/media/player/IjkMediaPlayer.java | 4 ++-- ijkmedia/ijkplayer/android/ijkplayer_jni.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java index 986a5ccff5..4baf2e1b8a 100755 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java @@ -979,9 +979,9 @@ public int startRecord(String recordVideoPath)throws IllegalStateException{ public int stopRecord()throws IllegalStateException{ return _stopRecord(); } - private native int _startRecord(String recordVideoPath)throws IllegalStateException; + private native int _startRecord(String recordVideoPath); - private native int _stopRecord()throws IllegalStateException; + private native int _stopRecord(); @Override public void setLogEnabled(boolean enable) { diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c index a42f3c2c68..3e7aa21a4e 100755 --- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c +++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c @@ -418,35 +418,40 @@ IjkMediaPlayer_reset(JNIEnv *env, jobject thiz) ijkmp_dec_ref_p(&mp); } + //开始录屏 static jint -IjkMediaPlayer_startRecord(JNIEnv *env, jclass thiz,jstring file) +IjkMediaPlayer_startRecord(JNIEnv *env, jobject thiz,jstring file) { jint retval = 0; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); - JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException","mpjni: startRecord: null mp", LABEL_RETURN); + JNI_CHECK_GOTO(mp, env, NULL, "mpjni: startRecord: null mp", LABEL_RETURN); const char *nativeString = (*env)->GetStringUTFChars(env, file, 0); retval = ijkmp_start_record(mp,nativeString); -LABEL_RETURN: + LABEL_RETURN: ijkmp_dec_ref_p(&mp); + retval=1; return retval; } + //结束录屏 static jint -IjkMediaPlayer_stopRecord(JNIEnv *env, jclass thiz) +IjkMediaPlayer_stopRecord(JNIEnv *env, jobject thiz) { jint retval = 0; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); - JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: stopRecord: null mp", LABEL_RETURN); + JNI_CHECK_GOTO(mp, env, NULL, "mpjni: stopRecord: null mp", LABEL_RETURN); retval = ijkmp_stop_record(mp); -LABEL_RETURN: + LABEL_RETURN: ijkmp_dec_ref_p(&mp); + retval=1; return retval; } + static void IjkMediaPlayer_setLoopCount(JNIEnv *env, jobject thiz, jint loop_count) { From 93973efbaad040bfefa6555f31beda56870639f3 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Fri, 30 Oct 2020 10:50:05 +0800 Subject: [PATCH 09/11] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BD=95=E5=B1=8Fjni?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tv/danmaku/ijk/media/player/IjkMediaPlayer.java | 4 ++-- ijkmedia/ijkplayer/android/ijkplayer_jni.c | 2 -- ijkmedia/ijkplayer/ijkplayer.c | 10 +++++++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java index 4baf2e1b8a..3de02b4ec1 100755 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java @@ -973,10 +973,10 @@ public MediaInfo getMediaInfo() { } return mediaInfo; } - public int startRecord(String recordVideoPath)throws IllegalStateException{ + public int startRecord(String recordVideoPath){ return _startRecord(recordVideoPath); } - public int stopRecord()throws IllegalStateException{ + public int stopRecord(){ return _stopRecord(); } private native int _startRecord(String recordVideoPath); diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c index 3e7aa21a4e..11596263c6 100755 --- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c +++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c @@ -431,7 +431,6 @@ IjkMediaPlayer_startRecord(JNIEnv *env, jobject thiz,jstring file) LABEL_RETURN: ijkmp_dec_ref_p(&mp); - retval=1; return retval; } @@ -447,7 +446,6 @@ IjkMediaPlayer_stopRecord(JNIEnv *env, jobject thiz) LABEL_RETURN: ijkmp_dec_ref_p(&mp); - retval=1; return retval; } diff --git a/ijkmedia/ijkplayer/ijkplayer.c b/ijkmedia/ijkplayer/ijkplayer.c index 0482a94e25..f7fad5b7a5 100755 --- a/ijkmedia/ijkplayer/ijkplayer.c +++ b/ijkmedia/ijkplayer/ijkplayer.c @@ -851,7 +851,15 @@ int ijkmp_start_record(IjkMediaPlayer *mp,const char *file_name) printf("=====开始录制准备====="); MPTRACE("ijkmp_startRecord()\n"); pthread_mutex_lock(&mp->mutex); - int retval = ffp_start_record(mp->ffplayer,file_name); + int retval = 1; + if(mp->ffplayer->is_record){ + //如果正在录制,先停止再开始 + ijkmp_stop_record(mp); + retval= ffp_start_record(mp->ffplayer,file_name); + }else{ + retval= ffp_start_record(mp->ffplayer,file_name); + } + printf("=====开始录制已调用=====\n"); pthread_mutex_unlock(&mp->mutex); MPTRACE("ijkmp_startRecord()=%d\n", retval); From 733e539daed0ce802ac0440ac7692be11747e4f9 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Fri, 6 Nov 2020 14:07:15 +0800 Subject: [PATCH 10/11] =?UTF-8?q?=E8=A7=86=E9=A2=91=E5=BD=95=E5=88=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ijkmedia/ijkplayer/ff_ffplay.c | 2 +- ijkmedia/ijkplayer/ijkplayer.c | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index af92b897ec..7576203171 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -5343,7 +5343,7 @@ int ffp_record_file(FFPlayer *ffp, AVPacket *packet) return -1; } - AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket)); // 与看直播的 AVPacket分开,不然卡屏 + AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket)+1); // 与看直播的 AVPacket分开,不然卡屏 av_new_packet(pkt, 0); if (0 == av_packet_ref(pkt, packet)) { diff --git a/ijkmedia/ijkplayer/ijkplayer.c b/ijkmedia/ijkplayer/ijkplayer.c index f7fad5b7a5..e89a0a9e18 100755 --- a/ijkmedia/ijkplayer/ijkplayer.c +++ b/ijkmedia/ijkplayer/ijkplayer.c @@ -850,18 +850,8 @@ int ijkmp_start_record(IjkMediaPlayer *mp,const char *file_name) assert(mp); printf("=====开始录制准备====="); MPTRACE("ijkmp_startRecord()\n"); - pthread_mutex_lock(&mp->mutex); - int retval = 1; - if(mp->ffplayer->is_record){ - //如果正在录制,先停止再开始 - ijkmp_stop_record(mp); - retval= ffp_start_record(mp->ffplayer,file_name); - }else{ - retval= ffp_start_record(mp->ffplayer,file_name); - } - + int retval = ffp_start_record(mp->ffplayer,file_name); printf("=====开始录制已调用=====\n"); - pthread_mutex_unlock(&mp->mutex); MPTRACE("ijkmp_startRecord()=%d\n", retval); return retval; } @@ -871,10 +861,8 @@ int ijkmp_stop_record(IjkMediaPlayer *mp) assert(mp); MPTRACE("ijkmp_stopRecord()\n"); printf("=====结束录制准备=====\n"); - pthread_mutex_lock(&mp->mutex); int retval = ffp_stop_record(mp->ffplayer); printf("=====结束录制已调用=====\n"); - pthread_mutex_unlock(&mp->mutex); MPTRACE("ijkmp_stopRecord()=%d\n", retval); return retval; } From abf7054fde957d9d99245314f1fd09e4f4aa8781 Mon Sep 17 00:00:00 2001 From: jhone <1226468643@qq.com> Date: Tue, 24 Nov 2020 20:09:19 +0800 Subject: [PATCH 11/11] =?UTF-8?q?=E5=BD=95=E5=88=B6=E8=BF=9B=E7=A8=8B?= =?UTF-8?q?=E5=8A=A0=E9=94=81=EF=BC=8Cpkt=20data=20=3D=3DNULL=E6=97=B6cras?= =?UTF-8?q?h=E9=97=AE=E9=A2=98=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ijkmedia/ijkplayer/android/ijkplayer_jni.c | 4 + ijkmedia/ijkplayer/ff_ffplay.c | 108 +++++++++++---------- ijkmedia/ijkplayer/ijkplayer.c | 4 + 3 files changed, 64 insertions(+), 52 deletions(-) diff --git a/ijkmedia/ijkplayer/android/ijkplayer_jni.c b/ijkmedia/ijkplayer/android/ijkplayer_jni.c index 11596263c6..3cb52846b9 100755 --- a/ijkmedia/ijkplayer/android/ijkplayer_jni.c +++ b/ijkmedia/ijkplayer/android/ijkplayer_jni.c @@ -425,11 +425,15 @@ IjkMediaPlayer_startRecord(JNIEnv *env, jobject thiz,jstring file) { jint retval = 0; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); + printf("########################"); + printf("%p",mp); JNI_CHECK_GOTO(mp, env, NULL, "mpjni: startRecord: null mp", LABEL_RETURN); const char *nativeString = (*env)->GetStringUTFChars(env, file, 0); retval = ijkmp_start_record(mp,nativeString); LABEL_RETURN: + printf("########################"); + printf("LABEL_RETURN"); ijkmp_dec_ref_p(&mp); return retval; } diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index 7576203171..3c4a5f7075 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -5307,6 +5307,7 @@ int ffp_stop_record(FFPlayer *ffp) av_log(NULL, AV_LOG_INFO, "===== 写文件尾部返回:%d =====\n",errorCode); if (ffp->m_ofmt_ctx && !(ffp->m_ofmt->flags & AVFMT_NOFILE)) { av_log(NULL, AV_LOG_INFO, "===== 开始关闭文件 =====\n"); + avio_closep(&ffp->m_ofmt_ctx->pb); avio_close(ffp->m_ofmt_ctx->pb); } avformat_free_context(ffp->m_ofmt_ctx); @@ -5343,69 +5344,72 @@ int ffp_record_file(FFPlayer *ffp, AVPacket *packet) return -1; } - AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket)+1); // 与看直播的 AVPacket分开,不然卡屏 + AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket)); // 与看直播的 AVPacket分开,不然卡屏 av_new_packet(pkt, 0); - if (0 == av_packet_ref(pkt, packet)) { - +// av_packet_alloc(); +// av_packet_from_data(pkt,packet->data,packet->size); + if(packet!=NULL && packet->size>0 && packet->data!=NULL){ + if (0 == av_packet_ref(pkt, packet)) { + av_log(ffp, AV_LOG_INFO, "ffp->start_pts:%"PRId64"",ffp->start_pts); + av_log(ffp, AV_LOG_INFO, "ffp->start_dts:%"PRId64"",ffp->start_dts); + + av_log(ffp, AV_LOG_INFO, "ffp->is_first:%d",ffp->is_first); + if (!ffp->is_first) { // 录制的第一帧,时间从0开始 + if(pkt->flags==AV_PKT_FLAG_KEY){ + //取到I帧开始写录制数据 + ffp->is_first = 1; + ffp->start_pts = pkt->pts; + ffp->start_dts = pkt->dts; + pkt->pts = 0; + pkt->dts = 0; + }else{ + ffp->is_first = 0; + ffp->start_pts = pkt->pts; + ffp->start_dts = pkt->dts; + pkt->pts = 0; + pkt->dts = 0; + av_packet_unref(pkt); + pthread_mutex_unlock(&ffp->record_mutex); + return 0; + } - av_log(ffp, AV_LOG_INFO, "ffp->start_pts:%"PRId64"",ffp->start_pts); - av_log(ffp, AV_LOG_INFO, "ffp->start_dts:%"PRId64"",ffp->start_dts); - - av_log(ffp, AV_LOG_INFO, "ffp->is_first:%d",ffp->is_first); - if (!ffp->is_first) { // 录制的第一帧,时间从0开始 - if(pkt->flags==AV_PKT_FLAG_KEY){ - //取到I帧开始写录制数据 - ffp->is_first = 1; - ffp->start_pts = pkt->pts; - ffp->start_dts = pkt->dts; - pkt->pts = 0; - pkt->dts = 0; - }else{ - ffp->is_first = 0; - ffp->start_pts = pkt->pts; - ffp->start_dts = pkt->dts; - pkt->pts = 0; - pkt->dts = 0; - av_packet_unref(pkt); - pthread_mutex_unlock(&ffp->record_mutex); - return 0; + } else { // 之后的每一帧都要减去,点击开始录制时的值,这样的时间才是正确的 + pkt->pts = llabs(pkt->pts - ffp->start_pts); + pkt->dts = llabs(pkt->dts - ffp->start_dts); } - - } else { // 之后的每一帧都要减去,点击开始录制时的值,这样的时间才是正确的 - pkt->pts = llabs(pkt->pts - ffp->start_pts); - pkt->dts = llabs(pkt->dts - ffp->start_dts); - } - - if(pkt->ptsdts) - pkt->dts = pkt->pts; - if(pkt->dtspts) - pkt->pts = pkt->dts; - in_stream = is->ic->streams[pkt->stream_index]; - out_stream = ffp->m_ofmt_ctx->streams[pkt->stream_index]; - // 转换PTS/DTS - pkt->pts = av_rescale_q_rnd(pkt->pts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); - pkt->dts = av_rescale_q_rnd(pkt->dts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); - pkt->duration = av_rescale_q(pkt->duration, in_stream->time_base, out_stream->time_base); + if(pkt->ptsdts) + pkt->dts = pkt->pts; + if(pkt->dtspts) + pkt->pts = pkt->dts; + in_stream = is->ic->streams[pkt->stream_index]; + out_stream = ffp->m_ofmt_ctx->streams[pkt->stream_index]; + + // 转换PTS/DTS + pkt->pts = av_rescale_q_rnd(pkt->pts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); + pkt->dts = av_rescale_q_rnd(pkt->dts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); + pkt->duration = av_rescale_q(pkt->duration, in_stream->time_base, out_stream->time_base); - pkt->pos = -1; + pkt->pos = -1; - av_log(ffp, AV_LOG_INFO, "inner pkt->pts:%"PRId64"\n",pkt->pts); - av_log(ffp, AV_LOG_INFO, "inner pkt->dts:%"PRId64"\n",pkt->dts); - av_log(ffp, AV_LOG_INFO, "inner pkt->duration:%"PRId64"\n",pkt->duration); + av_log(ffp, AV_LOG_INFO, "inner pkt->pts:%"PRId64"\n",pkt->pts); + av_log(ffp, AV_LOG_INFO, "inner pkt->dts:%"PRId64"\n",pkt->dts); + av_log(ffp, AV_LOG_INFO, "inner pkt->duration:%"PRId64"\n",pkt->duration); - av_log(ffp, AV_LOG_INFO, "av_interleaved_write_frame\n"); - // 写入一个AVPacket到输出文件 - if ((ret = av_interleaved_write_frame(ffp->m_ofmt_ctx, pkt)) < 0) { - av_log(ffp, AV_LOG_ERROR, "Error muxing packet\n"); + av_log(ffp, AV_LOG_INFO, "av_interleaved_write_frame\n"); + // 写入一个AVPacket到输出文件 + if ((ret = av_interleaved_write_frame(ffp->m_ofmt_ctx, pkt)) < 0) { + av_log(ffp, AV_LOG_ERROR, "Error muxing packet\n"); + } + av_packet_unref(pkt); + pthread_mutex_unlock(&ffp->record_mutex); + } else { + av_log(ffp, AV_LOG_ERROR, "av_packet_ref == NULL"); } - av_packet_unref(pkt); - pthread_mutex_unlock(&ffp->record_mutex); - } else { - av_log(ffp, AV_LOG_ERROR, "av_packet_ref == NULL"); } + } pthread_mutex_unlock(&ffp->record_mutex); return ret; diff --git a/ijkmedia/ijkplayer/ijkplayer.c b/ijkmedia/ijkplayer/ijkplayer.c index e89a0a9e18..3619ac1833 100755 --- a/ijkmedia/ijkplayer/ijkplayer.c +++ b/ijkmedia/ijkplayer/ijkplayer.c @@ -847,22 +847,26 @@ int ijkmp_get_msg(IjkMediaPlayer *mp, AVMessage *msg, int block) int ijkmp_start_record(IjkMediaPlayer *mp,const char *file_name) { + pthread_mutex_lock(&mp->mutex); assert(mp); printf("=====开始录制准备====="); MPTRACE("ijkmp_startRecord()\n"); int retval = ffp_start_record(mp->ffplayer,file_name); printf("=====开始录制已调用=====\n"); MPTRACE("ijkmp_startRecord()=%d\n", retval); + pthread_mutex_unlock(&mp->mutex); return retval; } int ijkmp_stop_record(IjkMediaPlayer *mp) { + pthread_mutex_lock(&mp->mutex); assert(mp); MPTRACE("ijkmp_stopRecord()\n"); printf("=====结束录制准备=====\n"); int retval = ffp_stop_record(mp->ffplayer); printf("=====结束录制已调用=====\n"); MPTRACE("ijkmp_stopRecord()=%d\n", retval); + pthread_mutex_unlock(&mp->mutex); return retval; }