Skip to content
Open

1 #1

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/ffmpeg/include",
"${workspaceFolder}/libs_win/develop/SDL2-2.0.9/include"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++98",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
36 changes: 36 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [

{//包含Debug配置
"name": "(gdb) 启动",//配置名称
"type": "cppdbg",//配置类型,对应cpptools提供的调试功能
"request": "launch",//请求配置类型,可以是启动/附加类型[launch/attach]
"program": "${workspaceFolder}/study_ffmpeg/7_/${fileBasenameNoExtension}",//待调试程序本地路径
"args": [//程序调试时传递给程序的命令行参数,设为空值
"build_avdio.h264",
"libx264"
],
"stopAtEntry": false,//改为true时程序暂停在程序入口位置,即main处打上断点
"cwd": "${fileDirname}",//调试程序时的工作目录,这里表示源码目录
"environment": [],//环境变量,设为空值
"externalConsole": false,//true:cmd窗口; false:Vscode的内置终端输出
"MIMode": "gdb",//指定连接的调试器,minGW64中调试程序->gdb
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
]
}
11 changes: 11 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"C_Cpp.errorSquiggles": "enabled",
"files.associations": {
"stdio.h": "c",
"log.h": "c",
"gen_pic_rgb": "c",
"sdl.h": "c",
"avcodec.h": "c",
"avutil.h": "c"
}
}
37 changes: 37 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"tasks": [
{//构建配置项
"type": "cppbuild", //任务类型,Vscode将预定义变量转义解析后直接传给command;shell->先打开shell再输入命令,因此args会经过shell再次解析
"label": "C/C++: gcc 生成活动文件", //任务名称
"command": "/usr/bin/gcc",//本地编译器路径
"args": [//包含传给gcc命令的参数,用于实现特定功能
"-g",//生成和调试有关的信息
"${file}",//指定编译文件为当前文件
"-o",//指定输出文件的路径和名称
"${fileDirname}/${fileBasenameNoExtension}",//修改.exe文件生成位置
"-lm",
"-I/usr/local/ffmpeg/include",
"-L/usr/local/ffmpeg/lib",
"-I/${workspaceFolder}/libs_win/develop/SDL2-2.0.9/include",
"-L/${workspaceFolder}/libs_win/develop/SDL2-2.0.9/lib",
"-lavutil",
"-lavformat",
"-lavcodec",
"-lswscale",
"-lSDL2"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {//包含很多task,归为group
"kind": "build",//表名该组任务类型是构建
"isDefault": true//表明此任务为此组任务中的默认任务
},
"detail": "调试器生成的任务。"
},
],
"version": "2.0.0"
}
1 change: 1 addition & 0 deletions audio.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "player.h"
#include "packet.h"
#include "frame.h"
#include "SDL_audio.h"

static void sdl_audio_callback(void *opaque, Uint8 *stream, int len);

Expand Down
2 changes: 2 additions & 0 deletions demux.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "demux.h"
#include "packet.h"
#include "SDL_events.h"
#include "SDL_mutex.h"

static int decode_interrupt_cb(void *ctx)
{
Expand Down
Binary file added output/test_log
Binary file not shown.
Empty file added resources/clock.aac
Empty file.
Empty file added resources/clock.h264
Empty file.
Binary file added study_ffmpeg/5_/cut_avdio
Binary file not shown.
195 changes: 195 additions & 0 deletions study_ffmpeg/5_/cut_avdio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#include<stdio.h>
#include<stdlib.h>
#include<libavutil/log.h>
#include<libavutil/avutil.h>
#include<libavformat/avformat.h>

int main(int argc, char* argv[])
{
// 1.处理一些参数;
int ret = -1;
char* src;
char* dst;
double starttime;
double endtime;

av_log_set_level(AV_LOG_DEBUG);
// cut src dst start end
if( argc < 5 ) {
av_log(NULL, AV_LOG_INFO, "arguments must be more than 3\n");
exit(-1);
}

src = argv[1];
dst = argv[2];
starttime = atof(argv[3]);
endtime = atof(argv[4]);


// 2.打开多媒体文件;

AVFormatContext *pFmtCtx = NULL;
if( (ret = avformat_open_input(&pFmtCtx, src, NULL, NULL)) < 0 ){
av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));
exit(-1);
}

// 4.打开目的文件的上下文
// AVFormatContext *oFmtCtx = avformat_alloc_context();
// if( !oFmtCtx ){
// av_log(NULL, AV_LOG_ERROR, "NO Memory!\n");
// goto _ERROR;
// }
// const AVOutputFormat *outFmt = av_guess_format(NULL, dst, NULL);
// oFmtCtx->oformat = outFmt;
AVFormatContext *oFmtCtx = NULL;
avformat_alloc_output_context2(&oFmtCtx, NULL, NULL, dst);
if( !oFmtCtx ){
av_log(NULL, AV_LOG_ERROR, "NO MEMORT!\n");
goto _ERROR;
}

int *stream_map = NULL;
int stream_idx = 0;
stream_map = av_calloc(pFmtCtx->nb_streams, sizeof(int));
if( !stream_map ){
av_log(NULL, AV_LOG_ERROR, "NO MEMORT!\n");
goto _ERROR;
}
for( int i=0 ; i < pFmtCtx->nb_streams ; i++ ){
AVStream *inStream = pFmtCtx->streams[i];
AVStream *outStream = NULL;
AVCodecParameters *inCodecPar = inStream->codecpar;
if( inCodecPar->codec_type != AVMEDIA_TYPE_AUDIO &&
inCodecPar->codec_type != AVMEDIA_TYPE_VIDEO &&
inCodecPar->codec_type != AVMEDIA_TYPE_SUBTITLE){
stream_map[i] = -1;
continue;
}
else{
stream_map[i] = stream_idx++ ;
outStream = avformat_new_stream(oFmtCtx, NULL);
if( !outStream ){
av_log(oFmtCtx, AV_LOG_ERROR, "NO MEMORT!\n");
goto _ERROR;
}
avcodec_parameters_copy(outStream->codecpar, inStream->codecpar);
outStream->codecpar->codec_tag = 0;
}
}


// 绑定
ret = avio_open2(&oFmtCtx->pb, dst, AVIO_FLAG_WRITE, NULL, NULL);
if( ret < 0 ){
av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
goto _ERROR;
}

// 7.写多媒体文件头到目的文件

ret = avformat_write_header(oFmtCtx, NULL);
if( ret < 0 ){
av_log(oFmtCtx, AV_LOG_ERROR, "%s\n", av_err2str(ret));
goto _ERROR;
}


// cut起作用的地方
// 很多视频的裁剪不准确,是因为视频有IPB帧,我们很有可能裁剪到了B帧(没有I帧无法解析),那么就必须向前或者向后来裁剪
// 这个函数表示,从流的哪个时间点截取文件
ret = av_seek_frame(pFmtCtx, -1, starttime * AV_TIME_BASE, AVSEEK_FLAG_BACKWARD);

if( ret < 0 ){
av_log(oFmtCtx, AV_LOG_ERROR, "%s", av_err2str(ret));
goto _ERROR;
}


int64_t *dts_start_time = av_calloc(pFmtCtx->nb_streams, sizeof(int64_t));
int64_t *pts_start_time = av_calloc(pFmtCtx->nb_streams, sizeof(int64_t));
for( int i = 0 ; i < pFmtCtx->nb_streams ; i++ ){
dts_start_time[i] = -1;
pts_start_time[i] = -1;
}
// 8.从源多媒体文件中读到音频/视频/字幕数据到目的文件中

// 0 1 2 3 4 5
// -1 1 -1 1 -1 1

// 0 1 2 3 4 5
// -1 0 -1 1 -1 2

AVPacket pkt;
while( av_read_frame(pFmtCtx, &pkt) >= 0) {
AVStream *inStream, *outStream;

if( dts_start_time[pkt.stream_index] == -1 && pkt.dts > 0 ){
dts_start_time[pkt.stream_index] = pkt.dts;
}

if( pts_start_time[pkt.stream_index] == -1 && pkt.pts > 0 ){
pts_start_time[pkt.stream_index] = pkt.pts;
}

inStream = pFmtCtx->streams[pkt.stream_index];
if( av_q2d(inStream->time_base) * pkt.pts > endtime ){
av_log(oFmtCtx, AV_LOG_INFO, "success!\n");
break;
}

if( stream_map[pkt.stream_index] < 0 ){
av_packet_unref(&pkt);
continue;
}

pkt.pts = pkt.pts - pts_start_time[pkt.stream_index];
pkt.dts = pkt.dts - dts_start_time[pkt.stream_index];
if( pkt.pts > pkt.dts ){
pkt.pts = pkt.dts;
}

pkt.stream_index = stream_map[pkt.stream_index];

outStream = oFmtCtx->streams[pkt.stream_index];
av_packet_rescale_ts(&pkt, inStream->time_base, outStream->time_base);
// pkt.pts = av_rescale_q_rnd(pkt.pts, inStream->time_base, outStream->time_base, (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
// pkt.dts = av_rescale_q_rnd(pkt.dts, inStream->time_base, outStream->time_base, (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
// pkt.duration = av_rescale_q(pkt.duration, inStream->time_base, outStream->time_base);
// pkt.stream_index = 0;
pkt.pos = -1;
av_interleaved_write_frame(oFmtCtx, &pkt);
av_packet_unref(&pkt);
}

// 9.写多媒体文件尾到文件中

av_write_trailer(oFmtCtx);

// 10.将申请的资源释放掉

_ERROR:
if( pFmtCtx ){
avformat_close_input(&pFmtCtx);
pFmtCtx = NULL;
}
if( oFmtCtx->pb ){
avio_close(oFmtCtx->pb);
}
if( oFmtCtx ){
avformat_free_context(oFmtCtx);
oFmtCtx = NULL;
}
if( stream_map ){
av_free(stream_map);
}
if( dts_start_time ){
av_free(dts_start_time);

}
if( pts_start_time ){
av_free(pts_start_time);
}
return 0;
}

Binary file added study_ffmpeg/5_/extra_audio
Binary file not shown.
Loading