Skip to content
Open
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
194 changes: 194 additions & 0 deletions ijkmedia/ijkplayer/ff_ffplay.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,19 @@ static int decoder_decode_frame(FFPlayer *ffp, Decoder *d, AVFrame *frame, AVSub
}
} while (d->queue->serial != d->pkt_serial);

// if (!ffp->is_first && pkt.pts == pkt.dts) {
// ffp->start_pts = pkt.pts;
// ffp->start_dts = pkt.dts;
// }

// if (ffp->is_record) {
// if (0 != ffp_record_file(ffp, &pkt)) {
// ffp->record_error = 1;
// ffp_stop_recording_l(ffp);
// printf("avcodec_send_packet stop\n");
// }
// }

if (pkt.data == flush_pkt.data) {
avcodec_flush_buffers(d->avctx);
d->finished = 0;
Expand Down Expand Up @@ -3099,6 +3112,167 @@ static int is_realtime(AVFormatContext *s)
return 0;
}

int ffp_start_recording_l(FFPlayer *ffp, const char *file_name)
{
assert(ffp);
VideoState *is = ffp->is;

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");
goto end;
}

if (!is || !is->ic || is->paused || is->abort_request) {
av_log(ffp, AV_LOG_ERROR, "is,is->ic,is->paused is invalid");
goto end;
}


av_log(ffp->is_record, AV_LOG_DEBUG, "NHATHM ------");
if (ffp->is_record) {
av_log(ffp, AV_LOG_ERROR, "recording has started");
av_log(ffp->is_record, AV_LOG_DEBUG, "NHATHM ------ 2");
goto end;
}

avformat_alloc_output_context2(&ffp->m_ofmt_ctx, NULL, NULL, file_name);
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 *in_stream = is->ic->streams[i];
AVStream *out_stream = avformat_new_stream(ffp->m_ofmt_ctx, in_stream->codec->codec);
if (!out_stream) {
av_log(ffp, AV_LOG_ERROR, "Failed allocating output stream\n");
goto end;
}

av_log(ffp, AV_LOG_DEBUG, "in_stream->codec;%p\n", in_stream->codec);
if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
av_log(ffp, AV_LOG_ERROR, "Failed to copy context from input to output stream codec context\n");
goto end;
}

out_stream->codec->codec_tag = 0;
if (ffp->m_ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
}

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;
}
}

if (avformat_write_header(ffp->m_ofmt_ctx, NULL) < 0) {
av_log(ffp, AV_LOG_ERROR, "Error occurred when opening output file\n");
goto end;
}

ffp->is_record = 1;
ffp->record_error = 0;
pthread_mutex_init(&ffp->record_mutex, NULL);

return 0;
end:
ffp->record_error = 1;
return -1;
}

int ffp_record_isfinished_l(FFPlayer *ffp)
{
return 0;
}

int ffp_record_file(FFPlayer *ffp, AVPacket *packet)
{
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");
return -1;
}

AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket));
av_new_packet(pkt, 0);
if (0 == av_packet_ref(pkt, packet)) {
pthread_mutex_lock(&ffp->record_mutex);
if (!ffp->is_first) {
ffp->is_first = 1;
pkt->pts = 0;
pkt->dts = 0;
} else {
if (pkt->stream_index == AVMEDIA_TYPE_AUDIO) {
pkt->pts = llabs(pkt->pts - ffp->start_a_pts);
pkt->dts = llabs(pkt->dts - ffp->start_a_dts);
}
else if (pkt->stream_index == AVMEDIA_TYPE_VIDEO) {
pkt->pts = pkt->dts = llabs(pkt->dts - ffp->start_v_dts);
}
}

in_stream = is->ic->streams[pkt->stream_index];
out_stream = ffp->m_ofmt_ctx->streams[pkt->stream_index];

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;

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");
}
}
return ret;
}

int ffp_stop_recording_l(FFPlayer *ffp){
assert(ffp);
if (ffp->is_record) {
ffp->is_record = 0;
pthread_mutex_lock(&ffp->record_mutex);
if (ffp->m_ofmt_ctx != NULL) {
av_write_trailer(ffp->m_ofmt_ctx);
if (ffp->m_ofmt_ctx && !(ffp->m_ofmt->flags & AVFMT_NOFILE)) {
avio_close(ffp->m_ofmt_ctx->pb);
}
avformat_free_context(ffp->m_ofmt_ctx);
ffp->m_ofmt_ctx = NULL;
ffp->is_first = 0;
}
pthread_mutex_unlock(&ffp->record_mutex);
pthread_mutex_destroy(&ffp->record_mutex);
av_log(ffp, AV_LOG_DEBUG, "stopRecord ok\n");
} else {
av_log(ffp, AV_LOG_ERROR, "don't need stopRecord\n");
}
return 0;
}

/* this thread gets the stream from the disk or the network */
static int read_thread(void *arg)
{
Expand Down Expand Up @@ -3392,6 +3566,26 @@ static int read_thread(void *arg)
}

for (;;) {
if (!ffp->is_first && pkt->pts == pkt->dts) {
if (pkt->stream_index == AVMEDIA_TYPE_AUDIO) {
ffp->start_a_pts = pkt->pts;
ffp->start_a_dts = pkt->dts;
}
}
if (pkt->stream_index == AVMEDIA_TYPE_VIDEO) {
if (!ffp->is_first) {
ffp->start_v_pts = pkt->pts;
ffp->start_v_dts = pkt->dts;
}
}

if (ffp->is_record) {
if (0 != ffp_record_file(ffp, pkt)) {
ffp->record_error = 1;
ffp_stop_recording_l(ffp);
}
}

if (is->abort_request)
break;
#ifdef FFP_MERGE
Expand Down
5 changes: 5 additions & 0 deletions ijkmedia/ijkplayer/ff_ffplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ int ffp_is_paused_l(FFPlayer *ffp);
int ffp_stop_l(FFPlayer *ffp);
int ffp_wait_stop_l(FFPlayer *ffp);

/* record rtsp streaming */
int ffp_start_recording_l(FFPlayer *ffp, const char *file_name);
int ffp_record_isfinished_l(FFPlayer *ffp);
int ffp_stop_recording_l(FFPlayer *ffp);

/* all in milliseconds */
int ffp_seek_to_l(FFPlayer *ffp, long msec);
long ffp_get_current_position_l(FFPlayer *ffp);
Expand Down
11 changes: 11 additions & 0 deletions ijkmedia/ijkplayer/ff_ffplay_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,17 @@ typedef struct FFPlayer {
char *mediacodec_default_name;
int ijkmeta_delay_init;
int render_wait_start;

AVFormatContext *m_ofmt_ctx;
AVOutputFormat *m_ofmt;
pthread_mutex_t record_mutex;
int is_record;
int record_error;
int is_first;
int64_t start_v_pts;
int64_t start_v_dts;
int64_t start_a_pts;
int64_t start_a_dts;
} FFPlayer;

#define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE))
Expand Down
51 changes: 51 additions & 0 deletions ijkmedia/ijkplayer/ijkplayer.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,3 +796,54 @@ int ijkmp_get_msg(IjkMediaPlayer *mp, AVMessage *msg, int block)

return -1;
}

static int ijkmp_start_recording_l(IjkMediaPlayer *mp, const char *filePath)
{
av_log(mp->ffplayer,AV_LOG_INFO,"cjz ijkmp_start_recording_l filePath %s",filePath);
return ffp_start_recording_l(mp->ffplayer, filePath);
}

int ijkmp_start_recording(IjkMediaPlayer *mp,const char *filePath)
{
assert(mp);
pthread_mutex_lock(&mp->mutex);
av_log(mp->ffplayer,AV_LOG_WARNING,"cjz ijkmp_start_recording --- ");
int retval = ijkmp_start_recording_l(mp,filePath);
printf("ijkmp_start_recording return == %d\n",retval);
pthread_mutex_unlock(&mp->mutex);
return retval;
}

static int ijkmp_stop_recording_l(IjkMediaPlayer *mp)
{
return ffp_stop_recording_l(mp->ffplayer);
}

int ijkmp_stop_recording(IjkMediaPlayer *mp)
{
assert(mp);
pthread_mutex_lock(&mp->mutex);
av_log(mp->ffplayer,AV_LOG_WARNING,"cjz ijkmp_stop_recording");
int retval = ijkmp_stop_recording_l(mp);
pthread_mutex_unlock(&mp->mutex);
return retval;
}

static int ijkmp_isRecordFinished_l(IjkMediaPlayer *mp)
{
return ffp_record_isfinished_l(mp->ffplayer);
}

int ijkmp_isRecordFinished(IjkMediaPlayer *mp)
{
assert(mp);
pthread_mutex_lock(&mp->mutex);
av_log(mp->ffplayer,AV_LOG_WARNING,"cjz ijkmp_isRecordFinished ");
int retval = ijkmp_isRecordFinished_l(mp);
pthread_mutex_unlock(&mp->mutex);
return retval;
}

int ijkmp_isRecording(IjkMediaPlayer *mp) {
return mp->ffplayer->is_record;
}
3 changes: 3 additions & 0 deletions ijkmedia/ijkplayer/ijkplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ struct SDL_Vout;
#define IJKMP_OPT_CATEGORY_PLAYER FFP_OPT_CATEGORY_PLAYER
#define IJKMP_OPT_CATEGORY_SWR FFP_OPT_CATEGORY_SWR

int ijkmp_start_recording(IjkMediaPlayer *mp, const char *filePath);
int ijkmp_stop_recording(IjkMediaPlayer *mp);
int ijkmp_isRecording(IjkMediaPlayer *mp);

void ijkmp_global_init();
void ijkmp_global_uninit();
Expand Down
6 changes: 3 additions & 3 deletions init-ios.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ fi
set -e
TOOLS=tools

FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386"
FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64"
FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
#FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386"
#FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64"
FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK
FF_TARGET=$1

Expand Down
Loading