Пример #1
0
main(int argc, char** argv)
{
	if (argc < 2) {
		fprintf(stderr, "Usage: %s <file>\n", argv[0]);
		exit(1);
	}

	u_int32_t verbosity = 0 /* MP4_DETAILS_ALL */;

	MP4FileHandle mp4File = MP4Create(argv[1], verbosity);

	if (!mp4File) {
		exit(1);
	}

	MP4TrackId urlTrackId = 
		MP4AddTrack(mp4File, "URLF");
	printf("urlTrackId %d\n", urlTrackId);

	u_int8_t i;
	char url[128];

	for (i = 1; i <= 5; i++) {
		sprintf(url, "http://server.com/foo/bar%u.html", i);

		MP4WriteSample(mp4File, urlTrackId, 
			(u_int8_t*)url, strlen(url) + 1, (MP4Duration)i);
	}

	MP4Close(mp4File);

	mp4File = MP4Read(argv[1], verbosity);

	// check that we can find the track again
	urlTrackId = MP4FindTrackId(mp4File, 0, "URLF");
	printf("urlTrackId %d\n", urlTrackId);
	
	for (i = 1; i <= 5; i++) {
		u_int8_t* pSample = NULL;
		u_int32_t sampleSize = 0;
		MP4Duration duration;
		bool rc;

		rc = MP4ReadSample(mp4File, urlTrackId, i,
			&pSample, &sampleSize, NULL, &duration);

		if (rc) {
			printf("Sample %i duration "D64": %s\n", 
				i, duration, pSample);
			free(pSample);
		} else {
			printf("Couldn't read sample %i\n", i);
		}
	}

	MP4Close(mp4File);

	exit(0);
}
Пример #2
0
int covert_aac_to_mp4(char *inputFileName, char *mp4FileName)
{
    int Mp4TimeScale = 90000;
    int allMpeg4Streams = 0;
    MP4FileHandle mp4File;
    FILE* inFile;
    const char *type;
    MP4TrackId createdTrackId = MP4_INVALID_TRACK_ID;

    mp4File = MP4Create(mp4FileName, 0, 0);
    if (mp4File)
    {
        MP4SetTimeScale(mp4File, Mp4TimeScale);
    } else {
        return 1;
    }

    inFile = fopen(inputFileName, "rb");

	if (inFile == NULL)
    {
        MP4Close(mp4File);
        return 2;
    }

    createdTrackId = AacCreator(mp4File, inFile);

    if (createdTrackId == MP4_INVALID_TRACK_ID)
    {
        fclose(inFile);
        MP4Close(mp4File);
        return 3;
    }

    type = MP4GetTrackType(mp4File, createdTrackId);

    if (!strcmp(type, MP4_AUDIO_TRACK_TYPE))
    {
        allMpeg4Streams &=
            (MP4GetTrackEsdsObjectTypeId(mp4File, createdTrackId)
            == MP4_MPEG4_AUDIO_TYPE);
    }

    if (inFile)
    {
        fclose(inFile);
    }

    MP4Close(mp4File);
    MP4MakeIsmaCompliant(mp4FileName, 0, allMpeg4Streams);

    return 0;
}
Пример #3
0
/**
    \fn close
    \brief Cleanup is done in the dtor
*/
bool muxerMp4v2::close(void)
{
    if(handle)
    {
            MP4Close(handle,ADM_MP4_OPTIONS_CLOSE);
//#warning run MP4Optimize
    }
    handle=NULL;
    if(audioTrackIds) delete [] audioTrackIds;
    audioTrackIds=NULL;
    if(audioPackets) delete [] audioPackets;
    audioPackets=NULL;
    for(int i=0;i<2;i++)
    {
        if(videoBuffer[i]) delete [] videoBuffer[i];
        videoBuffer[i]=NULL;
    }
    if(scratchBuffer)
        {
            delete [] scratchBuffer;
            scratchBuffer=NULL;
        }
    ADM_info("[Mp4v2Muxer] Closing\n");
    return true;
}
Пример #4
0
void Mp4Encoder::Stop()
{
	if (m_hMp4File) {
		MP4Close(m_hMp4File);
		m_hMp4File = NULL;
	}
}
void mpeg_video_recorder::StopRecording(){
	if (MP4_IS_VALID_FILE_HANDLE(m_hMp4FileHandle)){
		MP4Close(m_hMp4FileHandle);
	}

	m_IsRecording = false;
}
Пример #6
0
void MP4Encoder::CloseMP4File(MP4FileHandle hMp4File)
{
    if(hMp4File)
    {
        MP4Close(hMp4File);
        hMp4File = NULL;
    }
}
Пример #7
0
void SoundSourceM4A::close() {
    closeDecoder();
    m_sampleBuffer.reset();
    m_inputBuffer.clear();
    if (MP4_INVALID_FILE_HANDLE != m_hFile) {
        MP4Close(m_hFile);
        m_hFile = MP4_INVALID_FILE_HANDLE;
    }
}
Пример #8
0
    ~MP4Reader()
    {
        if (pSeqHeaders || pSeqHeaderSize || pPictHeaders || pPictHeaderSize) {
            MP4FreeH264SeqPictHeaders(pSeqHeaders, pSeqHeaderSize, pPictHeaders, pPictHeaderSize);
        }

        if (handle != MP4_INVALID_FILE_HANDLE) MP4Close(handle);
        if (video_sample) delete[] video_sample;
    }
Пример #9
0
CMp4File::~CMp4File (void)
{
  MP4Close(m_mp4file);
  m_mp4file = NULL;
  if (m_file_mutex) {
    SDL_DestroyMutex(m_file_mutex);
    m_file_mutex = NULL;
  }
}
Пример #10
0
void SoundSourceM4A::close() {
    if (m_hDecoder) {
        NeAACDecClose(m_hDecoder);
        m_hDecoder = NULL;
    }
    if (MP4_INVALID_FILE_HANDLE != m_hFile) {
        MP4Close(m_hFile);
        m_hFile = MP4_INVALID_FILE_HANDLE;
    }
    m_inputBuffer.clear();
}
Пример #11
0
AacPcm::~AacPcm()
{
	if(mp4File)
		MP4Close(mp4File);
	if(aacFile)
		fclose(aacFile);
	if(hDecoder)
		faacDecClose(hDecoder);
	FREE_ARRAY(buffer);
	FREE_ARRAY(seek_table);
}
Пример #12
0
int MP4Streamer::Close()
{
	Log(">MP4 Close\n");
	
	//Lock
	pthread_mutex_lock(&mutex);

	//Change  state
	opened = false;

	//If we have been opened
	if (mp4!=MP4_INVALID_FILE_HANDLE)
		// Close file
		MP4Close(mp4);

	//Unset handler
	mp4 = MP4_INVALID_FILE_HANDLE;

	//It it waas playing
	if (playing)
	{
		//Not playing
		playing = 0;

		//Signal
		pthread_cond_signal(&cond);

		//Get running thread
		DWORD running = thread;

		//Clean thread
		thread = NULL;

		//Unlock
		pthread_mutex_unlock(&mutex);

		//Check thread
		if (running)
			//Wait for running thread
			pthread_join(running,NULL);
	} else {
		//Unlock
		pthread_mutex_unlock(&mutex);
	}

	Log("<MP4 Close\n");

	return 1;
}
Пример #13
0
void CAVInfo::ReadMP4(const char *file)
{
	MP4FileHandle mp4File = MP4Read(file, MP4_DETAILS_ERROR);
	if ( !mp4File ) {
		return;
	}
	uint32_t vsize;
	uint8_t *value;
	char *pname = "moov.uuid.data";

	MP4GetBytesProperty(mp4File, pname, &value, &vsize);
	if ( vsize ) {
		MP4_moov_uuid_parse(value, vsize, m_title);
		free(value);
	}
	MP4Close(mp4File);
}
Пример #14
0
extern "C" char* MP4FileInfo(
	const char* fileName,
	MP4TrackId trackId)
{
	MP4FileHandle mp4File =
		MP4Read(fileName);

	if (!mp4File) {
		return NULL;
	}

	char* info = MP4Info(mp4File, trackId);

	MP4Close(mp4File);

	return info;	// caller should free this
}
Пример #15
0
int32_t Mp4FileDefaultAudio(const char* fileName)
{
	MP4FileHandle mp4File = MP4Read(fileName);

	if (mp4File == MP4_INVALID_FILE_HANDLE) {
		return -1;
	}

	MP4TrackId trackId = 
		MP4FindTrackId(mp4File, 0, MP4_AUDIO_TRACK_TYPE);

	MP4Close(mp4File);

	if (trackId == MP4_INVALID_TRACK_ID) {
		return -1;
	}
	return trackId;
}
Пример #16
0
int CMP4Tag::ReadMp4Tag(char *Filename)						 
{
MP4FileHandle MP4File;

	if(!(MP4File=MP4Read(Filename, 0)))
	{
	char buf[25+MAX_PATH+1];
		sprintf(buf,"ReadMp4Tag: can't open \"%s\"",Filename);
		MessageBox(NULL,buf,NULL,MB_OK);
		return 1;
	}

	FREE_ARRAY(copyright);
	MP4GetMetadataTool(MP4File, &copyright);

	FREE_ARRAY(artist);
	MP4GetMetadataArtist(MP4File, &artist);
	FREE_ARRAY(writer);
	MP4GetMetadataWriter(MP4File, &writer);
	FREE_ARRAY(title);
	MP4GetMetadataName(MP4File, &title);
	FREE_ARRAY(album);
	MP4GetMetadataAlbum(MP4File, &album);
	MP4GetMetadataTrack(MP4File, (unsigned __int16 *)&trackno, (unsigned __int16 *)&ntracks);
	MP4GetMetadataDisk(MP4File, (unsigned __int16 *)&discno, (unsigned __int16 *)&ndiscs);
	MP4GetMetadataCompilation(MP4File, (unsigned __int8 *)&compilation);
	FREE_ARRAY(year);
	MP4GetMetadataYear(MP4File, &year);
	FREE_ARRAY(genre);
	MP4GetMetadataGenre(MP4File, &genre);
	FREE_ARRAY(comment);
	MP4GetMetadataComment(MP4File, &comment);
	FREE_ARRAY(art.data);
	MP4GetMetadataCoverArt(MP4File, (unsigned __int8 **)&art.data, (u_int32_t *)&art.size);

	MP4Close(MP4File);
/*
	FILE *f=fopen("D:\\prova.jpg","wb");
		fwrite(artFile,1,artSize,f);
		fclose(f);*/
	return 0;
}
Пример #17
0
bool Strip_Tag(LPCSTR filename)
{
	// TODO:
	// remove tag from file.
	// do whatever is need to remove the supported tag from filename

	// return true for successfull strip, false for failure

	MP4FileHandle file;

	file = MP4Modify(filename, 0, 0);
	if (file == MP4_INVALID_FILE_HANDLE)
		return false;
	
	MP4MetadataDelete(file);

	MP4Close(file);

	return true;
}
Пример #18
0
static void
aac_free (DB_fileinfo_t *_info) {
    aac_info_t *info = (aac_info_t *)_info;
    if (info) {
        if (info->file) {
            deadbeef->fclose (info->file);
        }
        if (info->mp4file) {
#ifdef USE_MP4FF
            mp4ff_close (info->mp4file);
#else
            MP4Close (info->mp4file);
#endif
        }
        if (info->dec) {
            NeAACDecClose (info->dec);
        }
        free (info);
    }
}
Пример #19
0
static switch_status_t mp4_file_close(switch_file_handle_t *handle)
{
	mp4_file_context_t *context = handle->private_info;

	if (context->fd) {
		MP4Close(context->fd, 0);
		context->fd = NULL;
	}

	if (switch_core_codec_ready(&context->audio_codec)) switch_core_codec_destroy(&context->audio_codec);
	if (switch_core_codec_ready(&context->video_codec)) switch_core_codec_destroy(&context->video_codec);

	if (context->timer.interval) {
		switch_core_timer_destroy(&context->timer);
	}

	switch_img_free(&context->last_img);
	switch_buffer_destroy(&context->buf);

	return SWITCH_STATUS_SUCCESS;
}
Пример #20
0
int encoder_uninitialize(unsigned long id)
{
	if(!pestreams[id].firstwrite)
	{
		faacEncClose(pestreams[id].enchandle);

		sys_mem_free(pestreams[id].floatbuffer);
		sys_mem_free(pestreams[id].obuffer);
		sys_mem_free(pestreams[id].cachebuffer);


		if(!pestreams[id].ismp4)
		{
			sys_file_close(pestreams[id].fhandle);
		}else{
			MP4Close(pestreams[id].mp4file);
		}

		pestreams[id].firstwrite = 1;
	}
	return 1;
}
Пример #21
0
int aac_decode(aac_dec_opt *opt)
{
    int result;
    int def_srate = 0;
    int outfile_set = 0;
    int mp4file = 0;
    char *fnp;
    char audioFileName[MAX_PATH];
    MP4FileHandle infile;


    /* point to the specified file name */
    strcpy(audioFileName, opt->filename);

    fnp = (char *)strrchr(audioFileName,'.');

    if (fnp)
        fnp[0] = '\0';

    strcat(audioFileName, file_ext[opt->file_type]);

    mp4file = 1;
    infile = MP4Read(audioFileName, 0);
    if (!infile)
        mp4file = 0;
    if (infile) MP4Close(infile);

    if (mp4file)
    {
        result = decodeMP4file(audioFileName, opt);
    }
    else
    {
        result = decodeAACfile(audioFileName, def_srate, opt);
    }

    return 0;
}
Пример #22
0
int
main(int argc, char** argv)
{
    static struct option long_options[] = {
        { "help",    0, 0, OPT_HELP    },
        { "version", 0, 0, OPT_VERSION },
        { "album",   1, 0, OPT_ALBUM   },
        { "artist",  1, 0, OPT_ARTIST  },
        { "comment", 1, 0, OPT_COMMENT },
        { "disk",    1, 0, OPT_DISK    },
        { "disks",   1, 0, OPT_DISKS   },
        { "genre",   1, 0, OPT_GENRE   },
        { "song",    1, 0, OPT_SONG    },
        { "tempo",   1, 0, OPT_TEMPO   },
        { "track",   1, 0, OPT_TRACK   },
        { "tracks",  1, 0, OPT_TRACKS  },
        { "writer",  1, 0, OPT_WRITER  },
        { "year",    1, 0, OPT_YEAR    },
        { NULL,      0, 0, 0 }
    };

    /* Sparse arrays of tag data: some space is wasted, but it's more
       convenient to say tags[OPT_SONG] than to enumerate all the
       metadata types (again) as a struct. */
    char *tags[UCHAR_MAX] = { 0 };
    int nums[UCHAR_MAX] = { 0 };

    /* Any modifications requested? */
    int mods = 0;

    /* Option-processing loop. */
    int c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL);
    while (c != -1) {
        int r = 2;
        switch(c) {
        /* getopt() returns '?' if there was an error.  It already
           printed the error message, so just return. */
        case '?':
            return 1;

        /* Help and version requests handled here. */
        case OPT_HELP:
            fprintf(stderr, "usage %s %s", argv[0], help_text);
            return 0;
        case OPT_VERSION:
            fprintf(stderr, "%s - %s version %s\n", argv[0], MPEG4IP_PACKAGE,
                    MPEG4IP_VERSION);
            return 0;

        /* Numeric arguments: convert them using sscanf(). */
        case OPT_DISK:
        case OPT_DISKS:
        case OPT_TRACK:
        case OPT_TRACKS:
        case OPT_TEMPO:
            r = sscanf(optarg, "%d", &nums[c]);
            if (r < 1) {
                fprintf(stderr, "%s: option requires numeric argument -- %c\n",
                        argv[0], c);
                return 2;
            }
        /* Break not, lest ye be broken.  :) */
        /* All arguments: all valid options end up here, and we just
           stuff the string pointer into the tags[] array. */
        default:
            tags[c] = optarg;
            mods++;
        } /* end switch */

        c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL);
    } /* end while */

    /* Check that we have at least one non-option argument */
    if ((argc - optind) < 1) {
        fprintf(stderr,
                "%s: You must specify at least one MP4 file.\n",
                argv[0]);
        fprintf(stderr, "usage %s %s", argv[0], help_text);
        return 3;
    }

    /* Check that we have at least one requested modification.  Probably
       it's useful instead to print the metadata if no modifications are
       requested? */
    if (!mods) {
        fprintf(stderr,
                "%s: You must specify at least one tag modification.\n",
                argv[0]);
        fprintf(stderr, "usage %s %s", argv[0], help_text);
        return 4;
    }

    /* Loop through the non-option arguments, and modify the tags as
       requested. */
    while (optind < argc) {
        char *mp4 = argv[optind++];

        MP4FileHandle h = MP4Modify(mp4);
        if (h == MP4_INVALID_FILE_HANDLE) {
            fprintf(stderr, "Could not open '%s'... aborting\n", mp4);
            return 5;
        }

        /* Track/disk numbers need to be set all at once, but we'd like to
           allow users to just specify -T 12 to indicate that all existing
           track numbers are out of 12.  This means we need to look up the
           current info if it is not being set. */
        uint16_t n0, m0, n1, m1;

        if (tags[OPT_TRACK] || tags[OPT_TRACKS]) {
            MP4GetMetadataTrack(h, &n0, &m0);
            n1 = tags[OPT_TRACK]? nums[OPT_TRACK] : n0;
            m1 = tags[OPT_TRACKS]? nums[OPT_TRACKS] : m0;
            MP4SetMetadataTrack(h, n1, m1);
        }
        if (tags[OPT_DISK] || tags[OPT_DISKS]) {
            MP4GetMetadataDisk(h, &n0, &m0);
            n1 = tags[OPT_DISK]? nums[OPT_DISK] : n0;
            m1 = tags[OPT_DISKS]? nums[OPT_DISKS] : m0;
            MP4SetMetadataDisk(h, n1, m1);
        }

        /* Set the other relevant attributes */
        for (int i = 0;  i < UCHAR_MAX;  i++) {
            if (tags[i]) {
                switch(i) {
                case OPT_ALBUM:
                    MP4SetMetadataAlbum(h, tags[i]);
                    break;
                case OPT_ARTIST:
                    MP4SetMetadataArtist(h, tags[i]);
                    break;
                case OPT_COMMENT:
                    MP4SetMetadataComment(h, tags[i]);
                    break;
                case OPT_GENRE:
                    MP4SetMetadataGenre(h, tags[i]);
                    break;
                case OPT_SONG:
                    MP4SetMetadataName(h, tags[i]);
                    break;
                case OPT_WRITER:
                    MP4SetMetadataWriter(h, tags[i]);
                    break;
                case OPT_YEAR:
                    MP4SetMetadataYear(h, tags[i]);
                    break;
                case OPT_TEMPO:
                    MP4SetMetadataTempo(h, nums[i]);
                    break;
                }
            }
        }
        MP4Close(h);
    } /* end while optind < argc */

    return 0;
}
Пример #23
0
	void Context::close()
	{
		if (!isOpen()) return;
		MP4Close(fh);
	}
Пример #24
0
static switch_status_t mp4_file_open(switch_file_handle_t *handle, const char *path)
{
	mp4_file_context_t *context;
	char *ext;
	unsigned int flags = 0;
	const char *tmp = NULL;

	if ((ext = strrchr(path, '.')) == 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
		return SWITCH_STATUS_GENERR;
	}
	ext++;

	if ((context = switch_core_alloc(handle->memory_pool, sizeof(mp4_file_context_t))) == 0) {
		return SWITCH_STATUS_MEMERR;
	}

	memset(context, 0, sizeof(mp4_file_context_t));

	context->offset = -100;
	if (handle->params && (tmp = switch_event_get_header(handle->params, "mp4v2_video_offset"))) {
		context->offset = atoi(tmp);
	}

	context->audio_type = MP4_ULAW_AUDIO_TYPE; // default

	if (handle->params && (tmp = switch_event_get_header(handle->params, "mp4v2_audio_codec"))) {
		if (!strcasecmp(tmp, "PCMU")) {
			context->audio_type = MP4_ULAW_AUDIO_TYPE;
		} else if (!strcasecmp(tmp, "MP3")) {
			context->audio_type = MP4_MP3_AUDIO_TYPE;
		} else if (!strcasecmp(tmp, "AAC")) {
			context->audio_type = MP4_MPEG4_AUDIO_TYPE;
		} else if (!strcasecmp(tmp, "L16")) {
			context->audio_type = MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE;
		}
	}

	switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		flags |= SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE;
		if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND) || switch_test_flag(handle, SWITCH_FILE_WRITE_OVER)) {
			flags |= SWITCH_FOPEN_READ;
		} else {
			flags |= SWITCH_FOPEN_TRUNCATE;
		}
	}

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
		flags |= SWITCH_FOPEN_READ;
	}

	if ((context->fd = MP4CreateEx(path, 0, 1, 1, NULL, 0, NULL, 0)) == MP4_INVALID_FILE_HANDLE) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error opening file %s\n", path);
		return SWITCH_STATUS_GENERR;
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sample rate: %d, channels: %d\n", handle->samplerate, handle->channels);

	if (context->audio_type == MP4_ULAW_AUDIO_TYPE) {
		context->audio = MP4AddULawAudioTrack(context->fd, handle->samplerate);
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.ulaw.channels", handle->channels);
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.ulaw.sampleSize", 8);
	} else if (context->audio_type == MP4_MP3_AUDIO_TYPE) {
		// handle->samplerate = 44100;
		context->audio = MP4AddAudioTrack(context->fd, handle->samplerate, handle->samplerate, MP4_MP3_AUDIO_TYPE);
		MP4SetTrackName(context->fd, context->audio, ".mp3");
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.mp4a.channels", handle->channels);
		// MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd..mp3.channels", handle->channels);
	} else if (context->audio_type == MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE) {
		context->audio = MP4AddAudioTrack(context->fd, handle->samplerate, handle->samplerate, MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE);
		MP4SetTrackName(context->fd, context->audio, "lpcm");
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.mp4a.channels", handle->channels);
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.lpcm.channels", handle->channels);
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.lpcm.sampleSize", 16);
	} else if (context->audio_type == MP4_MPEG4_AUDIO_TYPE) {
		/* AAC object types */
		#define AAC_MAIN 1
		#define AAC_LOW  2
		#define AAC_SSR  3
		#define AAC_LTP  4

		uint16_t info = 0;

		info |= AAC_LOW << 11; // aacObjectType (5bit)
		info |= get_aac_sample_rate_index(handle->samplerate) << 7; //(4bit)
		info |= handle->channels << 3; //(4bit)
		info = htons(info);

		context->audio = MP4AddAudioTrack(context->fd, handle->samplerate, handle->samplerate, MP4_MPEG4_AUDIO_TYPE);
		MP4SetTrackESConfiguration(context->fd, context->audio, (uint8_t *)&info, sizeof(info));
		MP4SetTrackIntegerProperty(context->fd, context->audio, "mdia.minf.stbl.stsd.mp4a.channels", handle->channels);
	}

	handle->format = 0;
	handle->sections = 0;
	handle->seekable = 0;
	handle->speed = 0;
	handle->pos = 0;
	handle->private_info = context;
	context->pool = handle->memory_pool;

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening File [%s] %dhz %s\n",
		path, handle->samplerate, switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) ? " with VIDEO" : "");

	if (switch_core_codec_init(&context->audio_codec,
							   get_audio_codec_name(context->audio_type),
							   NULL,
							   NULL,
							   handle->samplerate,
							   20,//ms
							   handle->channels, SWITCH_CODEC_FLAG_ENCODE,
							   NULL, handle->memory_pool) == SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Audio Codec Activation Success\n");
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Audio Codec Activation Fail\n");
		goto end;
	}

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) {
		if (switch_core_codec_init(&context->video_codec,
								   "H264",
								   NULL,
								   NULL,
								   90000,
								   0,//ms
								   1, SWITCH_CODEC_FLAG_ENCODE,
								   NULL, handle->memory_pool) == SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video Codec H264 Activation Success\n");
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Video Codec H264 Activation Fail\n");
			goto end;
		}
	}

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		MP4SetAudioProfileLevel(context->fd, 0x7F);
	}

	switch_buffer_create_dynamic(&context->buf, 512, 512, 1024000);

	return SWITCH_STATUS_SUCCESS;

end:
	if (context->fd) {
		MP4Close(context->fd, 0);
		context->fd = NULL;
	}
	return SWITCH_STATUS_FALSE;
}
Пример #25
0
int main(int argc, char *argv[])
{
    int frames, currentFrame;
    faacEncHandle hEncoder;
    pcmfile_t *infile = NULL;

    unsigned long samplesInput, maxBytesOutput, totalBytesWritten=0;

    faacEncConfigurationPtr myFormat;
    unsigned int mpegVersion = MPEG2;
    unsigned int objectType = LOW;
    unsigned int useMidSide = 1;
    static unsigned int useTns = DEFAULT_TNS;
    enum container_format container = NO_CONTAINER;
    int optimizeFlag = 0;
    enum stream_format stream = ADTS_STREAM;
    int cutOff = -1;
    int bitRate = 0;
    unsigned long quantqual = 0;
    int chanC = 3;
    int chanLF = 4;

    char *audioFileName = NULL;
    char *aacFileName = NULL;
    char *aacFileExt = NULL;
    int aacFileNameGiven = 0;

    float *pcmbuf;
    int *chanmap = NULL;

    unsigned char *bitbuf;
    int samplesRead = 0;
    const char *dieMessage = NULL;

    int rawChans = 0; // disabled by default
    int rawBits = 16;
    int rawRate = 44100;
    int rawEndian = 1;

    int shortctl = SHORTCTL_NORMAL;

    FILE *outfile = NULL;

#ifdef HAVE_LIBMP4V2
    MP4FileHandle MP4hFile = MP4_INVALID_FILE_HANDLE;
    MP4TrackId MP4track = 0;
    unsigned int ntracks = 0, trackno = 0;
    unsigned int ndiscs = 0, discno = 0;
    u_int8_t compilation = 0;
    const char *artist = NULL, *title = NULL, *album = NULL, *year = NULL,
      *genre = NULL, *comment = NULL, *writer = NULL;
    u_int8_t *art = NULL;
    u_int64_t artSize = 0;
    u_int64_t total_samples = 0;
    u_int64_t encoded_samples = 0;
    unsigned int delay_samples;
    unsigned int frameSize;
#endif
    char *faac_id_string;
    char *faac_copyright_string;

#ifndef _WIN32
    // install signal handler
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#endif

    // get faac version
    if (faacEncGetVersion(&faac_id_string, &faac_copyright_string) == FAAC_CFG_VERSION)
    {
        fprintf(stderr, "Freeware Advanced Audio Coder\nFAAC %s\n\n", faac_id_string);
    }
    else
    {
        fprintf(stderr, __FILE__ "(%d): wrong libfaac version\n", __LINE__);
        return 1;
    }

    /* begin process command line */
    progName = argv[0];
    while (1) {
        static struct option long_options[] = {
            { "help", 0, 0, 'h'},
            { "long-help", 0, 0, 'H'},
            { "raw", 0, 0, 'r'},
            { "no-midside", 0, 0, NO_MIDSIDE_FLAG},
            { "cutoff", 1, 0, 'c'},
            { "quality", 1, 0, 'q'},
            { "pcmraw", 0, 0, 'P'},
            { "pcmsamplerate", 1, 0, 'R'},
            { "pcmsamplebits", 1, 0, 'B'},
            { "pcmchannels", 1, 0, 'C'},
            { "shortctl", 1, 0, SHORTCTL_FLAG},
            { "tns", 0, 0, TNS_FLAG},
            { "no-tns", 0, 0, NO_TNS_FLAG},
            { "mpeg-version", 1, 0, MPEGVERS_FLAG},
            { "obj-type", 1, 0, OBJTYPE_FLAG},
            { "license", 0, 0, 'L'},
#ifdef HAVE_LIBMP4V2
            { "createmp4", 0, 0, 'w'},
            { "optimize", 0, 0, 's'},
            { "artist", 1, 0, ARTIST_FLAG},
            { "title", 1, 0, TITLE_FLAG},
            { "album", 1, 0, ALBUM_FLAG},
            { "track", 1, 0, TRACK_FLAG},
            { "disc", 1, 0, DISC_FLAG},
            { "genre", 1, 0, GENRE_FLAG},
            { "year", 1, 0, YEAR_FLAG},
            { "cover-art", 1, 0, COVER_ART_FLAG},
            { "comment", 1, 0, COMMENT_FLAG},
        { "writer", 1, 0, WRITER_FLAG},
        { "compilation", 0, 0, COMPILATION_FLAG},
#endif
        { "pcmswapbytes", 0, 0, 'X'},
            { 0, 0, 0, 0}
        };
        int c = -1;
        int option_index = 0;

        c = getopt_long(argc, argv, "Hhb:m:o:rnc:q:PR:B:C:I:X"
#ifdef HAVE_LIBMP4V2
                        "ws"
#endif
            ,long_options, &option_index);

        if (c == -1)
            break;

        if (!c)
        {
          dieMessage = usage;
          break;
        }

        switch (c) {
    case 'o':
        {
            int l = strlen(optarg);
        aacFileName = malloc(l+1);
        memcpy(aacFileName, optarg, l);
        aacFileName[l] = '\0';
        aacFileNameGiven = 1;
        }
        break;
        case 'r': {
            stream = RAW_STREAM;
            break;
        }
        case NO_MIDSIDE_FLAG: {
            useMidSide = 0;
            break;
        }
        case 'c': {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0) {
                cutOff = i;
            }
            break;
        }
        case 'b': {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0)
            {
                bitRate = 1000 * i;
            }
            break;
        }
        case 'q':
        {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0)
            {
                if (i > 0 && i < 1000)
                    quantqual = i;
            }
            break;
        }
        case 'I':
            sscanf(optarg, "%d,%d", &chanC, &chanLF);
            break;
        case 'P':
            rawChans = 2; // enable raw input
            break;
        case 'R':
        {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0)
            {
                rawRate = i;
                rawChans = (rawChans > 0) ? rawChans : 2;
            }
            break;
        }
        case 'B':
        {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0)
            {
                if (i > 32)
                    i = 32;
                if (i < 8)
                    i = 8;
                rawBits = i;
                rawChans = (rawChans > 0) ? rawChans : 2;
            }
            break;
        }
        case 'C':
        {
            unsigned int i;
            if (sscanf(optarg, "%u", &i) > 0)
                rawChans = i;
            break;
        }
#ifdef HAVE_LIBMP4V2
        case 'w':
        container = MP4_CONTAINER;
            break;
        case 's':
        optimizeFlag = 1;
            break;
    case ARTIST_FLAG:
        artist = optarg;
        break;
    case WRITER_FLAG:
        writer = optarg;
        break;
    case TITLE_FLAG:
        title = optarg;
        break;
    case ALBUM_FLAG:
        album = optarg;
        break;
    case TRACK_FLAG:
        sscanf(optarg, "%d/%d", &trackno, &ntracks);
        break;
    case DISC_FLAG:
        sscanf(optarg, "%d/%d", &discno, &ndiscs);
        break;
    case COMPILATION_FLAG:
        compilation = 0x1;
        break;
    case GENRE_FLAG:
        genre = optarg;
        break;
    case YEAR_FLAG:
        year = optarg;
        break;
    case COMMENT_FLAG:
        comment = optarg;
        break;
    case COVER_ART_FLAG: {
        FILE *artFile = fopen(optarg, "rb");

        if(artFile) {
            u_int64_t r;

            fseek(artFile, 0, SEEK_END);
        artSize = ftell(artFile);

        art = malloc(artSize);

            fseek(artFile, 0, SEEK_SET);
        clearerr(artFile);

        r = fread(art, artSize, 1, artFile);

        if (r != 1) {
            dieMessage = "Error reading cover art file!\n";
            free(art);
            art = NULL;
        } else if (artSize < 12 || !check_image_header(art)) {
            /* the above expression checks the image signature */
            dieMessage = "Unsupported cover image file format!\n";
            free(art);
            art = NULL;
        }

        fclose(artFile);
        } else {
            dieMessage = "Error opening cover art file!\n";
        }

        break;
    }
#endif
        case SHORTCTL_FLAG:
            shortctl = atoi(optarg);
            break;
        case TNS_FLAG:
            useTns = 1;
            break;
        case NO_TNS_FLAG:
            useTns = 0;
            break;
    case MPEGVERS_FLAG:
            mpegVersion = atoi(optarg);
            switch(mpegVersion)
            {
            case 2:
                mpegVersion = MPEG2;
                break;
            case 4:
                mpegVersion = MPEG4;
                break;
            default:
            dieMessage = "Unrecognised MPEG version!\n";
            }
            break;
#if 0
    case OBJTYPE_FLAG:
        if (!strcasecmp(optarg, "LC"))
                objectType = LOW;
        else if (!strcasecmp(optarg, "Main"))
            objectType = MAIN;
        else if (!strcasecmp(optarg, "LTP")) {
            mpegVersion = MPEG4;
        objectType = LTP;
        } else
            dieMessage = "Unrecognised object type!\n";
        break;
#endif
        case 'L':
        fprintf(stderr, faac_copyright_string);
        dieMessage = license;
        break;
    case 'X':
      rawEndian = 0;
      break;
    case 'H':
      dieMessage = long_help;
      break;
    case 'h':
          dieMessage = short_help;
      break;
    case '?':
        default:
      dieMessage = usage;
          break;
        }
    }

    /* check that we have at least one non-option arguments */
    if (!dieMessage && (argc - optind) > 1 && aacFileNameGiven)
        dieMessage = "Cannot encode several input files to one output file.\n";

    if (argc - optind < 1 || dieMessage)
    {
        fprintf(stderr, dieMessage ? dieMessage : usage,
           progName, progName, progName, progName);
        return 1;
    }

    while (argc - optind > 0) {

    /* get the input file name */
    audioFileName = argv[optind++];

    /* generate the output file name, if necessary */
    if (!aacFileNameGiven) {
        char *t = strrchr(audioFileName, '.');
    int l = t ? strlen(audioFileName) - strlen(t) : strlen(audioFileName);

#ifdef HAVE_LIBMP4V2
    aacFileExt = container == MP4_CONTAINER ? ".m4a" : ".aac";
#else
    aacFileExt = ".aac";
#endif

    aacFileName = malloc(l+1+4);
    memcpy(aacFileName, audioFileName, l);
    memcpy(aacFileName + l, aacFileExt, 4);
    aacFileName[l+4] = '\0';
    } else {
        aacFileExt = strrchr(aacFileName, '.');

        if (aacFileExt && (!strcmp(".m4a", aacFileExt) || !strcmp(".m4b", aacFileExt) || !strcmp(".mp4", aacFileExt)))
#ifndef HAVE_LIBMP4V2
        fprintf(stderr, "WARNING: MP4 support unavailable!\n");
#else
        container = MP4_CONTAINER;
#endif
    }

    /* open the audio input file */
    if (rawChans > 0) // use raw input
    {
        infile = wav_open_read(audioFileName, 1);
    if (infile)
    {
        infile->bigendian = rawEndian;
        infile->channels = rawChans;
        infile->samplebytes = rawBits / 8;
        infile->samplerate = rawRate;
        infile->samples /= (infile->channels * infile->samplebytes);
    }
    }
    else // header input
        infile = wav_open_read(audioFileName, 0);

    if (infile == NULL)
    {
        fprintf(stderr, "Couldn't open input file %s\n", audioFileName);
    return 1;
    }


    /* open the encoder library */
    hEncoder = faacEncOpen(infile->samplerate, infile->channels,
        &samplesInput, &maxBytesOutput);

#ifdef HAVE_LIBMP4V2
    if (container != MP4_CONTAINER && (ntracks || trackno || artist ||
                       title ||  album || year || art ||
                       genre || comment || discno || ndiscs ||
                       writer || compilation))
    {
        fprintf(stderr, "Metadata requires MP4 output!\n");
    return 1;
    }

    if (container == MP4_CONTAINER)
    {
        mpegVersion = MPEG4;
    stream = RAW_STREAM;
    }

    frameSize = samplesInput/infile->channels;
    delay_samples = frameSize; // encoder delay 1024 samples
#endif
    pcmbuf = (float *)malloc(samplesInput*sizeof(float));
    bitbuf = (unsigned char*)malloc(maxBytesOutput*sizeof(unsigned char));
    chanmap = mkChanMap(infile->channels, chanC, chanLF);
    if (chanmap)
    {
        fprintf(stderr, "Remapping input channels: Center=%d, LFE=%d\n",
            chanC, chanLF);
    }

    if (cutOff <= 0)
    {
        if (cutOff < 0) // default
            cutOff = 0;
        else // disabled
            cutOff = infile->samplerate / 2;
    }
    if (cutOff > (infile->samplerate / 2))
        cutOff = infile->samplerate / 2;

    /* put the options in the configuration struct */
    myFormat = faacEncGetCurrentConfiguration(hEncoder);
    myFormat->aacObjectType = objectType;
    myFormat->mpegVersion = mpegVersion;
    myFormat->useTns = useTns;
    switch (shortctl)
    {
    case SHORTCTL_NOSHORT:
      fprintf(stderr, "disabling short blocks\n");
      myFormat->shortctl = shortctl;
      break;
    case SHORTCTL_NOLONG:
      fprintf(stderr, "disabling long blocks\n");
      myFormat->shortctl = shortctl;
      break;
    }
    if (infile->channels >= 6)
        myFormat->useLfe = 1;
    myFormat->allowMidside = useMidSide;
    if (bitRate)
        myFormat->bitRate = bitRate / infile->channels;
    myFormat->bandWidth = cutOff;
    if (quantqual > 0)
        myFormat->quantqual = quantqual;
    myFormat->outputFormat = stream;
    myFormat->inputFormat = FAAC_INPUT_FLOAT;
    if (!faacEncSetConfiguration(hEncoder, myFormat)) {
        fprintf(stderr, "Unsupported output format!\n");
#ifdef HAVE_LIBMP4V2
        if (container == MP4_CONTAINER) MP4Close(MP4hFile);
#endif
        return 1;
    }

#ifdef HAVE_LIBMP4V2
    /* initialize MP4 creation */
    if (container == MP4_CONTAINER) {
        unsigned char *ASC = 0;
        unsigned long ASCLength = 0;
    char *version_string;

#ifdef MP4_CREATE_EXTENSIBLE_FORMAT
    /* hack to compile against libmp4v2 >= 1.0RC3
     * why is there no version identifier in mp4.h? */
        MP4hFile = MP4Create(aacFileName, MP4_DETAILS_ERROR, 0);
#else
    MP4hFile = MP4Create(aacFileName, MP4_DETAILS_ERROR, 0, 0);
#endif
        if (!MP4_IS_VALID_FILE_HANDLE(MP4hFile)) {
            fprintf(stderr, "Couldn't create output file %s\n", aacFileName);
            return 1;
        }

        MP4SetTimeScale(MP4hFile, 90000);
        MP4track = MP4AddAudioTrack(MP4hFile, infile->samplerate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
        MP4SetAudioProfileLevel(MP4hFile, 0x0F);
        faacEncGetDecoderSpecificInfo(hEncoder, &ASC, &ASCLength);
        MP4SetTrackESConfiguration(MP4hFile, MP4track, ASC, ASCLength);
    free(ASC);

    /* set metadata */
    version_string = malloc(strlen(faac_id_string) + 6);
    strcpy(version_string, "FAAC ");
    strcpy(version_string + 5, faac_id_string);
    MP4SetMetadataTool(MP4hFile, version_string);
    free(version_string);

    if (artist) MP4SetMetadataArtist(MP4hFile, artist);
    if (writer) MP4SetMetadataWriter(MP4hFile, writer);
    if (title) MP4SetMetadataName(MP4hFile, title);
    if (album) MP4SetMetadataAlbum(MP4hFile, album);
    if (trackno > 0) MP4SetMetadataTrack(MP4hFile, trackno, ntracks);
    if (discno > 0) MP4SetMetadataDisk(MP4hFile, discno, ndiscs);
    if (compilation) MP4SetMetadataCompilation(MP4hFile, compilation);
    if (year) MP4SetMetadataYear(MP4hFile, year);
    if (genre) MP4SetMetadataGenre(MP4hFile, genre);
    if (comment) MP4SetMetadataComment(MP4hFile, comment);
        if (artSize) {
        MP4SetMetadataCoverArt(MP4hFile, art, artSize);
        free(art);
    }
    }
    else
    {
#endif
        /* open the aac output file */
        if (!strcmp(aacFileName, "-"))
        {
            outfile = stdout;
        }
        else
        {
            outfile = fopen(aacFileName, "wb");
        }
        if (!outfile)
        {
            fprintf(stderr, "Couldn't create output file %s\n", aacFileName);
            return 1;
        }
#ifdef HAVE_LIBMP4V2
    }
#endif

    cutOff = myFormat->bandWidth;
    quantqual = myFormat->quantqual;
    bitRate = myFormat->bitRate;
    if (bitRate)
      fprintf(stderr, "Average bitrate: %d kbps\n",
          (bitRate + 500)/1000*infile->channels);
    fprintf(stderr, "Quantization quality: %ld\n", quantqual);
    fprintf(stderr, "Bandwidth: %d Hz\n", cutOff);
    fprintf(stderr, "Object type: ");
    switch(objectType)
    {
    case LOW:
        fprintf(stderr, "Low Complexity");
        break;
    case MAIN:
        fprintf(stderr, "Main");
        break;
    case LTP:
        fprintf(stderr, "LTP");
        break;
    }
    fprintf(stderr, "(MPEG-%d)", (mpegVersion == MPEG4) ? 4 : 2);
    if (myFormat->useTns)
        fprintf(stderr, " + TNS");
    if (myFormat->allowMidside)
        fprintf(stderr, " + M/S");
    fprintf(stderr, "\n");

    fprintf(stderr, "Container format: ");
    switch(container)
    {
    case NO_CONTAINER:
      switch(stream)
    {
    case RAW_STREAM:
      fprintf(stderr, "Headerless AAC (RAW)\n");
      break;
    case ADTS_STREAM:
      fprintf(stderr, "Transport Stream (ADTS)\n");
      break;
    }
        break;
#ifdef HAVE_LIBMP4V2
    case MP4_CONTAINER:
        fprintf(stderr, "MPEG-4 File Format (MP4)\n");
        break;
#endif
    }

    if (outfile
#ifdef HAVE_LIBMP4V2
        || MP4hFile != MP4_INVALID_FILE_HANDLE
#endif
       )
    {
        int showcnt = 0;
#ifdef _WIN32
        long begin = GetTickCount();
#endif
        if (infile->samples)
            frames = ((infile->samples + 1023) / 1024) + 1;
        else
            frames = 0;
        currentFrame = 0;

        fprintf(stderr, "Encoding %s to %s\n", audioFileName, aacFileName);
        if (frames != 0)
            fprintf(stderr, "   frame          | bitrate | elapsed/estim | "
            "play/CPU | ETA\n");
        else
            fprintf(stderr, " frame | elapsed | play/CPU\n");

        /* encoding loop */
#ifdef _WIN32
    for (;;)
#else
        while (running)
#endif
        {
            int bytesWritten;

            samplesRead = wav_read_float32(infile, pcmbuf, samplesInput, chanmap);

#ifdef HAVE_LIBMP4V2
            total_samples += samplesRead / infile->channels;
#endif

            /* call the actual encoding routine */
            bytesWritten = faacEncEncode(hEncoder,
                (int32_t *)pcmbuf,
                samplesRead,
                bitbuf,
                maxBytesOutput);

            if (bytesWritten)
            {
                currentFrame++;
                showcnt--;
        totalBytesWritten += bytesWritten;
            }

            if ((showcnt <= 0) || !bytesWritten)
            {
                double timeused;
#ifdef __unix__
                struct rusage usage;
#endif
#ifdef _WIN32
                char percent[MAX_PATH + 20];
                timeused = (GetTickCount() - begin) * 1e-3;
#else
#ifdef __unix__
                if (getrusage(RUSAGE_SELF, &usage) == 0) {
                    timeused = (double)usage.ru_utime.tv_sec +
                        (double)usage.ru_utime.tv_usec * 1e-6;
                }
                else
                    timeused = 0;
#else
                timeused = (double)clock() * (1.0 / CLOCKS_PER_SEC);
#endif
#endif
                if (currentFrame && (timeused > 0.1))
                {
                    showcnt += 50;

                    if (frames != 0)
                        fprintf(stderr,
                            "\r%5d/%-5d (%3d%%)|  %5.1f  | %6.1f/%-6.1f | %7.2fx | %.1f ",
                            currentFrame, frames, currentFrame*100/frames,
                ((double)totalBytesWritten * 8.0 / 1000.0) /
                ((double)infile->samples / infile->samplerate * currentFrame / frames),
                            timeused,
                            timeused * frames / currentFrame,
                            (1024.0 * currentFrame / infile->samplerate) / timeused,
                            timeused  * (frames - currentFrame) / currentFrame);
                    else
                        fprintf(stderr,
                            "\r %5d |  %6.1f | %7.2fx ",
                            currentFrame,
                            timeused,
                            (1024.0 * currentFrame / infile->samplerate) / timeused);

                    fflush(stderr);
#ifdef _WIN32
                    if (frames != 0)
                    {
                        sprintf(percent, "%.2f%% encoding %s",
                            100.0 * currentFrame / frames, audioFileName);
                        SetConsoleTitle(percent);
                    }
#endif
                }
            }

            /* all done, bail out */
            if (!samplesRead && !bytesWritten)
                break ;

            if (bytesWritten < 0)
            {
                fprintf(stderr, "faacEncEncode() failed\n");
                break ;
            }

            if (bytesWritten > 0)
            {
#ifdef HAVE_LIBMP4V2
                u_int64_t samples_left = total_samples - encoded_samples + delay_samples;
                MP4Duration dur = samples_left > frameSize ? frameSize : samples_left;
                MP4Duration ofs = encoded_samples > 0 ? 0 : delay_samples;

                if (container == MP4_CONTAINER)
                {
                    /* write bitstream to mp4 file */
                    MP4WriteSample(MP4hFile, MP4track, bitbuf, bytesWritten, dur, ofs, 1);
                }
                else
                {
#endif
                    /* write bitstream to aac file */
                    fwrite(bitbuf, 1, bytesWritten, outfile);
#ifdef HAVE_LIBMP4V2
                }

                encoded_samples += dur;
#endif
            }
        }

#ifdef HAVE_LIBMP4V2
        /* clean up */
        if (container == MP4_CONTAINER)
        {
            MP4Close(MP4hFile);
            if (optimizeFlag == 1)
            {
                fprintf(stderr, "\n\nMP4 format optimization... ");
                MP4Optimize(aacFileName, NULL, 0);
                fprintf(stderr, "Done!");
            }
        } else
#endif
            fclose(outfile);

        fprintf(stderr, "\n\n");
    }

    faacEncClose(hEncoder);

    wav_close(infile);

    if (pcmbuf) free(pcmbuf);
    if (bitbuf) free(bitbuf);
    if (aacFileNameGiven) free(aacFileName);

    }

    return 0;
}
Пример #26
0
static DB_playItem_t *
aac_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
    trace ("adding %s\n", fname);
    DB_FILE *fp = deadbeef->fopen (fname);
    if (!fp) {
        trace ("not found\n");
        return NULL;
    }
    aac_info_t info = {0};
    info.junk = deadbeef->junk_get_leading_size (fp);
    if (info.junk >= 0) {
        trace ("junk: %d\n", info.junk);
        deadbeef->fseek (fp, info.junk, SEEK_SET);
    }
    else {
        info.junk = 0;
    }

    const char *ftype = NULL;
    float duration = -1;
    int totalsamples = 0;
    int samplerate = 0;
    int channels = 0;

    int mp4track = -1;
    MP4FILE mp4 = NULL;

    if (fp->vfs->is_streaming ()) {
        trace ("streaming aac (%s)\n", fname);
        ftype = "RAW AAC";
    }
    else {

        // slowwww!
        info.file = fp;
        MP4FILE_CB cb = {
#ifdef USE_MP4FF
            .read = aac_fs_read,
            .write = NULL,
            .seek = aac_fs_seek,
            .truncate = NULL,
            .user_data = &info
#else
            .open = aac_fs_open,
            .seek = aac_fs_seek,
            .read = aac_fs_read,
            .write = NULL,
            .close = aac_fs_close
#endif
        };

        int res = aac_probe (fp, fname, &cb, &duration, &samplerate, &channels, &totalsamples, &mp4track, &mp4);
        if (res == -1) {
            deadbeef->fclose (fp);
            return NULL;
        }
        else if (res == 0) {
            ftype = "MP4 AAC";
        }
        else if (res == 1) {
            ftype = "RAW AAC";
        }
    }

    DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
    deadbeef->pl_add_meta (it, ":FILETYPE", ftype);
    deadbeef->plt_set_item_duration (plt, it, duration);
    trace ("duration: %f sec\n", duration);

    // read tags
    if (mp4) {
#ifdef USE_MP4FF
        aac_load_tags (it, mp4);
        mp4ff_close (mp4);
#else
        const MP4Tags *tags = MP4TagsAlloc ();
        MP4TagsFetch (tags, mp4);

        deadbeef->pl_add_meta (it, "title", tags->name);
        deadbeef->pl_add_meta (it, "artist", tags->artist);
        deadbeef->pl_add_meta (it, "albumArtist", tags->albumArtist);
        deadbeef->pl_add_meta (it, "album", tags->album);
        deadbeef->pl_add_meta (it, "composer", tags->composer);
        deadbeef->pl_add_meta (it, "comments", tags->comments);
        deadbeef->pl_add_meta (it, "genre", tags->genre);
        deadbeef->pl_add_meta (it, "year", tags->releaseDate);
        char s[10];
        if (tags->track) {
            snprintf (s, sizeof (s), "%d", tags->track->index);
            deadbeef->pl_add_meta (it, "track", s);
            snprintf (s, sizeof (s), "%d", tags->track->total);
            deadbeef->pl_add_meta (it, "numtracks", s);
        }
        if (tags->disk) {
            snprintf (s, sizeof (s), "%d", tags->disk->index);
            deadbeef->pl_add_meta (it, "disc", s);
            snprintf (s, sizeof (s), "%d", tags->disk->total);
            deadbeef->pl_add_meta (it, "numdiscs", s);
        }
        deadbeef->pl_add_meta (it, "copyright", tags->copyright);
        deadbeef->pl_add_meta (it, "vendor", tags->encodedBy);
        deadbeef->pl_add_meta (it, "title", NULL);
        MP4TagsFree (tags);
        MP4Close (mp4);
#endif
    }

    int apeerr = deadbeef->junk_apev2_read (it, fp);
    int v2err = deadbeef->junk_id3v2_read (it, fp);
    int v1err = deadbeef->junk_id3v1_read (it, fp);
    deadbeef->pl_add_meta (it, "title", NULL);

    int64_t fsize = deadbeef->fgetlength (fp);

    deadbeef->fclose (fp);

    if (duration > 0) {
        char s[100];
        snprintf (s, sizeof (s), "%lld", fsize);
        deadbeef->pl_add_meta (it, ":FILE_SIZE", s);
        deadbeef->pl_add_meta (it, ":BPS", "16");
        snprintf (s, sizeof (s), "%d", channels);
        deadbeef->pl_add_meta (it, ":CHANNELS", s);
        snprintf (s, sizeof (s), "%d", samplerate);
        deadbeef->pl_add_meta (it, ":SAMPLERATE", s);
        int br = (int)roundf(fsize / duration * 8 / 1000);
        snprintf (s, sizeof (s), "%d", br);
        deadbeef->pl_add_meta (it, ":BITRATE", s);
        // embedded cue
        deadbeef->pl_lock ();
        const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
        DB_playItem_t *cue = NULL;

        if (cuesheet) {
            cue = deadbeef->plt_insert_cue_from_buffer (plt, after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
            if (cue) {
                deadbeef->pl_item_unref (it);
                deadbeef->pl_item_unref (cue);
                deadbeef->pl_unlock ();
                return cue;
            }
        }
        deadbeef->pl_unlock ();

        cue  = deadbeef->plt_insert_cue (plt, after, it, totalsamples, samplerate);
        if (cue) {
            deadbeef->pl_item_unref (it);
            deadbeef->pl_item_unref (cue);
            return cue;
        }
    }

    deadbeef->pl_add_meta (it, "title", NULL);

    after = deadbeef->plt_insert_item (plt, after, it);
    deadbeef->pl_item_unref (it);
    return after;
}

static const char * exts[] = { "aac", "mp4", "m4a", NULL };

// define plugin interface
static DB_decoder_t plugin = {
    .plugin.api_vmajor = 1,
    .plugin.api_vminor = 0,
    .plugin.version_major = 1,
    .plugin.version_minor = 0,
    .plugin.type = DB_PLUGIN_DECODER,
    .plugin.id = "aac",
    .plugin.name = "AAC player",
    .plugin.descr = "plays aac files, supports raw aac files, as well as mp4 container",
    .plugin.copyright = 
        "Copyright (C) 2009-2012 Alexey Yakovenko <*****@*****.**>\n"
        "\n"
        "Uses modified libmp4ff (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com\n"
        "\n"
        "This program is free software; you can redistribute it and/or\n"
        "modify it under the terms of the GNU General Public License\n"
        "as published by the Free Software Foundation; either version 2\n"
        "of the License, or (at your option) any later version.\n"
        "\n"
        "This program is distributed in the hope that it will be useful,\n"
        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
        "GNU General Public License for more details.\n"
        "\n"
        "You should have received a copy of the GNU General Public License\n"
        "along with this program; if not, write to the Free Software\n"
        "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\n"
    ,
    .plugin.website = "http://deadbeef.sf.net",
    .open = aac_open,
    .init = aac_init,
    .free = aac_free,
    .read = aac_read,
    .seek = aac_seek,
    .seek_sample = aac_seek_sample,
    .insert = aac_insert,
    .read_metadata = aac_read_metadata,
#ifdef USE_MP4FF
    // mp4ff metadata writer doesn't work
    // .write_metadata = aac_write_metadata,
#else
#endif
    .exts = exts,
};

DB_plugin_t *
aac_load (DB_functions_t *api) {
    deadbeef = api;
    return DB_PLUGIN (&plugin);
}
Пример #27
0
// returns -1 for error, 0 for mp4, 1 for aac
int
aac_probe (DB_FILE *fp, const char *fname, MP4FILE_CB *cb, float *duration, int *samplerate, int *channels, int *totalsamples, int *mp4track, MP4FILE *pmp4) {
    // try mp4
    trace ("aac_probe: pos=%lld, junk=%d\n", deadbeef->ftell (fp), ((aac_info_t*)cb->user_data)->junk);

    if (mp4track) {
        *mp4track = -1;
    }
    if (*pmp4) {
        *pmp4 = NULL;
    }
    *duration = -1;
#ifdef USE_MP4FF
    trace ("mp4ff_open_read\n");
    mp4ff_t *mp4 = mp4ff_open_read (cb);
#else
    MP4FileHandle mp4 = MP4ReadProvider (fname, 0, cb);
#endif
    if (!mp4) {
        trace ("not an mp4 file\n");
        return -1;
    }
    if (pmp4) {
        *pmp4 = mp4;
    }
#ifdef USE_MP4FF
    int ntracks = mp4ff_total_tracks (mp4);
    if (ntracks > 0) {
        trace ("m4a container detected, ntracks=%d\n", ntracks);
        int i = -1;
        trace ("looking for mp4 data...\n");
        int sr = -1;
        unsigned char*  buff = 0;
        unsigned int    buff_size = 0;
        for (i = 0; i < ntracks; i++) {
            mp4AudioSpecificConfig mp4ASC;
            mp4ff_get_decoder_config(mp4, i, &buff, &buff_size);
            if (buff) {
                int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
                sr = mp4ASC.samplingFrequency;
                if(rc < 0) {
                    free (buff);
                    buff = 0;
                    continue;
                }
                break;
            }
        }
        if (i != ntracks && buff) 
        {
            trace ("found audio track (%d)\n", i);
            // init mp4 decoding
            NeAACDecHandle dec = NeAACDecOpen ();
            unsigned long srate;
            unsigned char ch;
            if (NeAACDecInit2(dec, buff, buff_size, &srate, &ch) < 0) {
                trace ("NeAACDecInit2 returned error\n");
                goto error;
            }
            *samplerate = srate;
            *channels = ch;
            int samples = mp4ff_num_samples(mp4, i);
            samples = (int64_t)samples * srate / mp4ff_time_scale (mp4, i);
            int tsamples = samples;
            NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (dec);
            conf->dontUpSampleImplicitSBR = 1;
            NeAACDecSetConfiguration (dec, conf);
            mp4AudioSpecificConfig mp4ASC;
            int mp4framesize;
            if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
            {
                mp4framesize = 1024;
                if (mp4ASC.frameLengthFlag == 1) {
                    mp4framesize = 960;
                }
                // commented this out, since it fixes double-duration bug on
                // some mp4 files
                //if (mp4ASC.sbr_present_flag == 1) {
                //    mp4framesize *= 2;
                //}
            }
            else {
                trace ("NeAACDecAudioSpecificConfig failed, can't get mp4framesize\n");
                goto error;
            }
            tsamples *= mp4framesize;

            trace ("mp4 nsamples=%d, samplerate=%d, timescale=%d, duration=%lld\n", samples, *samplerate, mp4ff_time_scale(mp4, i), mp4ff_get_track_duration(mp4, i));
            *duration = (float)tsamples / (*samplerate);
            trace ("mp4 duration: %f (tsamples %d/samplerate %d)\n", *duration, tsamples, *samplerate);
            
            NeAACDecClose (dec);

            if (totalsamples) {
                *totalsamples = tsamples;
            }
            if (mp4track) {
                *mp4track = i;
            }
            if (!*pmp4) {
                mp4ff_close (mp4);
            }
            return 0;
error:
            NeAACDecClose (dec);
            free (buff);
            if (!*pmp4) {
                mp4ff_close (mp4);
            }
            return -1;
        }
        else {
            trace ("audio track not found\n");
            mp4ff_close (mp4);
            mp4 = NULL;
        }
        if (buff) {
            free (buff);
            buff = NULL;
        }

    }
#else
    MP4FileHandle mp4File = mp4;
    MP4TrackId trackId = MP4FindTrackId(mp4File, 0, "audio", 0);
    trace ("trackid: %d\n", trackId);
    uint32_t timeScale = MP4GetTrackTimeScale(mp4File, trackId);
    MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId);
    MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId);
    u_int8_t* pConfig;
    uint32_t configSize = 0;
    bool res = MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize);
    if (res && pConfig) {
        mp4AudioSpecificConfig mp4ASC;
        int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC);
        free (pConfig);
        if (rc >= 0) {
            *samplerate = mp4ASC.samplingFrequency;
            *channels = MP4GetTrackAudioChannels (mp4File, trackId);
//            int64_t duration = MP4ConvertFromTrackDuration (mp4File, trackId, trackDuration, timeScale);
            int samples = MP4GetTrackNumberOfSamples (mp4File, trackId) * 1024 * (*channels);
            trace ("mp4 nsamples=%d, timescale=%d, samplerate=%d\n", samples, timeScale, *samplerate);
            *duration = (float)samples / (*samplerate);

            if (totalsamples) {
                *totalsamples = samples;
            }
            if (mp4track) {
                *mp4track = trackId;
            }
            if (!*pmp4) {
                MP4Close (mp4);
            }
            return 0;
        }
    }
#endif
    if (*pmp4) {
        *pmp4 = NULL;
    }

    if (mp4) {
#if USE_MP4FF
        mp4ff_close (mp4);
#else
        MP4Close (mp4);
#endif
        mp4 = NULL;
    }
    trace ("mp4 track not found, looking for aac stream...\n");

    // not an mp4, try raw aac
#if USE_MP4FF
    deadbeef->rewind (fp);
#endif
    if (parse_aac_stream (fp, samplerate, channels, duration, totalsamples) == -1) {
        trace ("aac stream not found\n");
        return -1;
    }
    trace ("found aac stream\n");
    return 1;
}
Пример #28
0
static int
aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    aac_info_t *info = (aac_info_t *)_info;

    info->file = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
    if (!info->file) {
        return -1;
    }

    // probe
    float duration = -1;
    int samplerate = -1;
    int channels = -1;
    int totalsamples = -1;

    info->junk = deadbeef->junk_get_leading_size (info->file);
    if (!info->file->vfs->is_streaming ()) {
        if (info->junk >= 0) {
            deadbeef->fseek (info->file, info->junk, SEEK_SET);
        }
        else {
            info->junk = 0;
        }
    }
    else {
        deadbeef->fset_track (info->file, it);
    }

    info->mp4track = -1;
#if USE_MP4FF
    info->mp4reader.read = aac_fs_read;
    info->mp4reader.write = NULL;
    info->mp4reader.seek = aac_fs_seek;
    info->mp4reader.truncate = NULL;
    info->mp4reader.user_data = info;
#else
    info->mp4reader.open = aac_fs_open;
    info->mp4reader.seek = aac_fs_seek;
    info->mp4reader.read = aac_fs_read;
    info->mp4reader.write = NULL;
    info->mp4reader.close = aac_fs_close;
#endif

    if (!info->file->vfs->is_streaming ()) {
#ifdef USE_MP4FF
        trace ("aac_init: mp4ff_open_read %s\n", deadbeef->pl_find_meta (it, ":URI"));
        info->mp4file = mp4ff_open_read (&info->mp4reader);
        if (info->mp4file) {
            int ntracks = mp4ff_total_tracks (info->mp4file);
            if (ntracks > 0) {
                trace ("m4a container detected, ntracks=%d\n", ntracks);
                int i = -1;
                unsigned char*  buff = 0;
                unsigned int    buff_size = 0;
                for (i = 0; i < ntracks; i++) {
                    mp4AudioSpecificConfig mp4ASC;
                    mp4ff_get_decoder_config (info->mp4file, i, &buff, &buff_size);
                    if(buff){
                        int rc = AudioSpecificConfig(buff, buff_size, &mp4ASC);
                        if(rc < 0)
                            continue;
                        break;
                    }
                }
                trace ("mp4 probe-buffer size: %d\n", buff_size);

                if (i != ntracks && buff) 
                {
                    trace ("mp4 track: %d\n", i);
                    int samples = mp4ff_num_samples(info->mp4file, i);
                    info->mp4samples = samples;
                    info->mp4track = i;

                    // init mp4 decoding
                    info->dec = NeAACDecOpen ();
                    unsigned long srate;
                    unsigned char ch;
                    if (NeAACDecInit2(info->dec, buff, buff_size, &srate, &ch) < 0) {
                        trace ("NeAACDecInit2 returned error\n");
                        free (buff);
                        return -1;
                    }
                    samplerate = srate;
                    channels = ch;
                    samples = (int64_t)samples * srate / mp4ff_time_scale (info->mp4file, i);
                    totalsamples = samples;
                    NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
                    conf->dontUpSampleImplicitSBR = 1;
                    NeAACDecSetConfiguration (info->dec, conf);
                    mp4AudioSpecificConfig mp4ASC;
                    if (NeAACDecAudioSpecificConfig(buff, buff_size, &mp4ASC) >= 0)
                    {
                        info->mp4framesize = 1024;
                        if (mp4ASC.frameLengthFlag == 1) {
                            info->mp4framesize = 960;
                        }
//                        if (mp4ASC.sbr_present_flag == 1) {
//                            info->mp4framesize *= 2;
//                        }
                    }
                    totalsamples *= info->mp4framesize;
                    duration = (float)totalsamples  / samplerate;
                }
                else {
                    mp4ff_close (info->mp4file);
                    info->mp4file = NULL;
                }
                if (buff) {
                    free (buff);
                }
            }
            else {
                mp4ff_close (info->mp4file);
                info->mp4file = NULL;
            }
        }
// {{{ libmp4v2 code
#else
        trace ("aac_init: MP4ReadProvider %s\n", deadbeef->pl_find_meta (it, ":URI"));
        info->mp4file = MP4ReadProvider (deadbeef->pl_find_meta (it, ":URI"), 0, &info->mp4reader);
        info->mp4track = MP4FindTrackId(info->mp4file, 0, "audio", 0);
        trace ("aac_init: MP4FindTrackId returned %d\n", info->mp4track);
        if (info->mp4track >= 0) {
            info->timescale = MP4GetTrackTimeScale(info->mp4file, info->mp4track);

            u_int8_t* pConfig;
            uint32_t configSize = 0;
            bool res = MP4GetTrackESConfiguration(info->mp4file, info->mp4track, &pConfig, &configSize);

            mp4AudioSpecificConfig mp4ASC;
            int rc = AudioSpecificConfig(pConfig, configSize, &mp4ASC);
            if (rc >= 0) {
                _info->samplerate = mp4ASC.samplingFrequency;
                _info->channels = MP4GetTrackAudioChannels (info->mp4file, info->mp4track);
                totalsamples = MP4GetTrackNumberOfSamples (info->mp4file, info->mp4track) * 1024 * _info->channels;

                // init mp4 decoding
                info->dec = NeAACDecOpen ();
                unsigned long srate;
                unsigned char ch;
                if (NeAACDecInit2(info->dec, pConfig, configSize, &srate, &ch) < 0) {
                    trace ("NeAACDecInit2 returned error\n");
                    return -1;
                }
                samplerate = srate;
                channels = ch;
                NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
                conf->dontUpSampleImplicitSBR = 1;
                NeAACDecSetConfiguration (info->dec, conf);
                mp4AudioSpecificConfig mp4ASC;
                if (NeAACDecAudioSpecificConfig(pConfig, configSize, &mp4ASC) >= 0)
                {
                    info->mp4framesize = 1024;
                    if (mp4ASC.frameLengthFlag == 1) {
                        info->mp4framesize = 960;
                    }
//                    if (mp4ASC.sbr_present_flag == 1) {
//                        info->mp4framesize *= 2;
//                    }
                }
                //totalsamples *= info->mp4framesize;
                free (pConfig);
                info->maxSampleSize = MP4GetTrackMaxSampleSize(info->mp4file, info->mp4track);
                info->samplebuffer = malloc (info->maxSampleSize);
                info->mp4sample = 1;
            }
            else {
                MP4Close (info->mp4file);
                info->mp4file = NULL;
            }
        }
        else {
            MP4Close (info->mp4file);
            info->mp4file = NULL;
        }
#endif
// }}}
        if (!info->mp4file) {
            trace ("mp4 track not found, looking for aac stream...\n");

            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, &totalsamples);
            if (offs == -1) {
                trace ("aac stream not found\n");
                return -1;
            }
            if (offs > info->junk) {
                info->junk = offs;
            }
            if (info->junk >= 0) {
                deadbeef->fseek (info->file, info->junk, SEEK_SET);
            }
            else {
                deadbeef->rewind (info->file);
            }
            trace ("found aac stream (junk: %d, offs: %d)\n", info->junk, offs);
        }

        _info->fmt.channels = channels;
        _info->fmt.samplerate = samplerate;
    }
    else {
        // sync before attempting to init
        int samplerate, channels;
        float duration;
        int offs = parse_aac_stream (info->file, &samplerate, &channels, &duration, NULL);
        if (offs < 0) {
            trace ("aac: parse_aac_stream failed\n");
            return -1;
        }
        if (offs > info->junk) {
            info->junk = offs;
        }
        trace("parse_aac_stream returned %x\n", offs);
        deadbeef->pl_replace_meta (it, "!FILETYPE", "AAC");
    }

//    duration = (float)totalsamples / samplerate;
//    deadbeef->pl_set_item_duration (it, duration);

    _info->fmt.bps = 16;
    _info->plugin = &plugin;

    if (!info->mp4file) {
        //trace ("NeAACDecGetCapabilities\n");
        //unsigned long caps = NeAACDecGetCapabilities();

        trace ("NeAACDecOpen\n");
        info->dec = NeAACDecOpen ();

        trace ("prepare for NeAACDecInit: fread %d from offs %lld\n", AAC_BUFFER_SIZE, deadbeef->ftell (info->file));
        info->remaining = deadbeef->fread (info->buffer, 1, AAC_BUFFER_SIZE, info->file);

        NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration (info->dec);
//        conf->dontUpSampleImplicitSBR = 1;
        NeAACDecSetConfiguration (info->dec, conf);
        unsigned long srate;
        unsigned char ch;
        trace ("NeAACDecInit (%d bytes)\n", info->remaining);
        int consumed = NeAACDecInit (info->dec, info->buffer, info->remaining, &srate, &ch);
        trace ("NeAACDecInit returned samplerate=%d, channels=%d, consumed: %d\n", (int)srate, (int)ch, consumed);
        if (consumed < 0) {
            trace ("NeAACDecInit returned %d\n", consumed);
            return -1;
        }
        if (consumed > info->remaining) {
            trace ("NeAACDecInit consumed more than available! wtf?\n");
            return -1;
        }
        if (consumed == info->remaining) {
            info->remaining = 0;
        }
        else if (consumed > 0) {
            memmove (info->buffer, info->buffer + consumed, info->remaining - consumed);
            info->remaining -= consumed;
        }
        _info->fmt.channels = ch;
        _info->fmt.samplerate = srate;
    }

    if (!info->file->vfs->is_streaming ()) {
        if (it->endsample > 0) {
            info->startsample = it->startsample;
            info->endsample = it->endsample;
            plugin.seek_sample (_info, 0);
        }
        else {
            info->startsample = 0;
            info->endsample = totalsamples-1;
        }
    }
    trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100);

    for (int i = 0; i < _info->fmt.channels; i++) {
        _info->fmt.channelmask |= 1 << i;
    }
    info->noremap = 0;
    info->remap[0] = -1;
    trace ("init success\n");

    return 0;
}
Пример #29
0
int decodeMP4file(char *sndfile, aac_dec_opt *opt)
{
    int track;
    unsigned long samplerate;
    unsigned char channels;
    void *sample_buffer;

    MP4FileHandle infile;
    MP4SampleId sampleId, numSamples;

    audio_file *aufile;

    faacDecHandle hDecoder;
    faacDecFrameInfo frameInfo;

    unsigned char *buffer;
    int buffer_size;

    int first_time = 1;

    hDecoder = faacDecOpen();

    infile = MP4Read(opt->filename, 0);
    if (!infile)
    {
        /* unable to open file */
        error_handler("Error opening file: %s\n", opt->filename);
        return 1;
    }

    if ((track = GetAACTrack(infile)) < 0)
    {
        error_handler("Unable to find correct AAC sound track in the MP4 file.\n");
        MP4Close(infile);
        return 1;
    }

    buffer = NULL;
    buffer_size = 0;
    MP4GetTrackESConfiguration(infile, track, &buffer, &buffer_size);

    if(faacDecInit2(hDecoder, buffer, buffer_size, &samplerate, &channels) < 0)
    {
        /* If some error initializing occured, skip the file */
        error_handler("Error initializing decoder library.\n");
        faacDecClose(hDecoder);
        MP4Close(infile);
        return 1;
    }
    if (buffer)
        free(buffer);

    numSamples = MP4GetTrackNumberOfSamples(infile, track);

    for (sampleId = 1; sampleId <= numSamples; sampleId++)
    {
        int rc;

        /* get access unit from MP4 file */
        buffer = NULL;
        buffer_size = 0;

        rc = MP4ReadSample(infile, track, sampleId, &buffer, &buffer_size, NULL, NULL, NULL, NULL);
        if (rc == 0)
        {
            error_handler("Reading from MP4 file failed.\n");
            faacDecClose(hDecoder);
            MP4Close(infile);
            return 1;
        }

        sample_buffer = faacDecDecode(hDecoder, &frameInfo, buffer, buffer_size);

        if (buffer)
            free(buffer);

        opt->progress_update((long)numSamples, sampleId);

        /* open the sound file now that the number of channels are known */
        if (first_time && !frameInfo.error)
        {
            if(opt->decode_mode == 0)
            {
                if (Set_WIN_Params (INVALID_FILEDESC, samplerate, SAMPLE_SIZE,
                                frameInfo.channels) < 0)
                {
                    error_handler("\nCan't access %s\n", "WAVE OUT");
                    faacDecClose(hDecoder);
                    MP4Close(infile);
                    return (0);
                }
            }
            else
            {
                aufile = open_audio_file(sndfile, samplerate, frameInfo.channels,
                     opt->output_format, opt->file_type, aacChannelConfig2wavexChannelMask(&frameInfo));

                if (aufile == NULL)
                {
                    faacDecClose(hDecoder);
                    MP4Close(infile);
                    return 0;
                }
            }
            first_time = 0;
        }

        if ((frameInfo.error == 0) && (frameInfo.samples > 0))
        {
            if(opt->decode_mode == 0)
                WIN_Play_Samples((short*)sample_buffer, frameInfo.channels*frameInfo.samples);
            else
                write_audio_file(aufile, sample_buffer, frameInfo.samples, 0);
        }

        if (frameInfo.error > 0)
        {
            error_handler("Error: %s\n",
            faacDecGetErrorMessage(frameInfo.error));
            break;
        }
        if(stop_decoding)
            break;
    }


    faacDecClose(hDecoder);


    MP4Close(infile);

    if(opt->decode_mode == 0)
        WIN_Audio_close();
    else
    {
        if (!first_time)
            close_audio_file(aufile);
    }

    return frameInfo.error;
}
Пример #30
0
bool mediaM4A(Artwork *art, const char *filePath)
{
    MP4FileHandle mp4file = MP4Read(filePath);
    if (mp4file == MP4_INVALID_FILE_HANDLE) {
        return false;
    }

    uint16_t numvalue, numvalue2;
    char *value;
    u_int8_t numbool;

    art->filetype = FILETYPE_M4A;

    if (MP4GetMetadataArtist(mp4file, &value) && value != NULL)
    {
        art->artist = (QString::fromUtf8(value)).trimmed();
        free(value);
    }
    if (MP4GetMetadataYear(mp4file, &value) && value != NULL)
    {
        art->year = QString(value).toInt();
        free(value);
    }

    if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL)
    {
        art->album = (QString::fromUtf8(value)).trimmed();
        free(value);
    }

    if (MP4GetMetadataName(mp4file, &value) && value != NULL)
    {
        art->track = (QString::fromUtf8(value)).trimmed();
        free(value);
    }

    if (MP4GetMetadataWriter(mp4file, &value) && value != NULL)
    {
        // composer
        free(value);
    }

    if (MP4GetMetadataTrack(mp4file, &numvalue, &numvalue2))
    {
        art->trackNo = numvalue;
        art->trackCount = numvalue2;
    }

    if (MP4GetMetadataDisk(mp4file, &numvalue, &numvalue2))
    {
        art->discNo = numvalue;
        art->discCount = numvalue2;
    }

    if (MP4GetMetadataGenre(mp4file, &value) && value != NULL)
    {
        art->genre = (QString::fromUtf8(value)).trimmed();
        free(value);
    }

    if (MP4GetMetadataCompilation(mp4file, &numbool))
    {
        art->type = numbool ? ARTWORK_COMPILATION : ARTWORK_NORMAL;
    }

    /*
    art->bitrate = 0;
    art->sampleRate = 0;
    art->channels = 0;
    */

    MP4Duration duration = MP4GetDuration(mp4file);
    if (duration != MP4_INVALID_DURATION) {
        u_int64_t timescale = MP4GetTimeScale(mp4file);
        u_int64_t msectime = (duration * (u_int64_t) 1000) / timescale;
        u_int64_t sectime, mintime, hrtime;

        if (msectime == 0) {
            hrtime = mintime = sectime = (u_int64_t) 0;
        }
        else {
            hrtime = msectime / (u_int64_t) (3600 * 1000);
            msectime -= hrtime * (u_int64_t) (3600 * 1000);
            mintime = msectime / (u_int64_t) (60 * 1000);
            msectime -= (mintime * (u_int64_t) (60 * 1000));
            sectime = msectime / (u_int64_t) (1000);
            msectime -= sectime * (u_int64_t)(1000);
        }

        art->duration = hrtime * 3600 + mintime * 60 + sectime;
    }

    art->makeSearchable();
    if (!art->hasCover()) {
        uint8_t *cover = NULL;
        uint32_t cover_size;

        if (MP4GetMetadataCoverArt(mp4file, &cover, &cover_size)) {
            if (saveImage(art, (const char*) cover, cover_size)) {
                qDebug() << "MP4: invalid image in " << filePath;
            }
        }

        if (cover) {
            free(cover);
        }
    }

    MP4Close(mp4file);

    return true;
}